【TensorFlow代码笔记】c_api.h

本文探讨了TensorFlow系统结构中的C API,它作为前端与后端的分界,前端负责计算图构建和Session管理,后端处理计算图执行。前端通过Swig生成的Python Wrapper与C实现交互,而动态链接库加载确保了Python到C函数的调用。c_api.h和c_api.cc文件中包含了函数符号表的静态注册,用于运行时匹配Python函数名并调用C实现。
摘要由CSDN通过智能技术生成

TensorFlow的系统结构以C API为界,将整个系统分为「前端」和「后端」两个子系统:

·        前端系统:主要扮演Client的角色,主要负责计算图的构造,并管理Session生命周期过程。是一个支持多语言的编程环境,并提供统一的编程模型支撑用户构造计算图。Client通过Session,连接TensorFlow后端的「运行时」,启动计算图的执行过程。

·        后端系统:TensorFlow的运行时系统,主要负责计算图的执行过程,包括计算图的剪枝,设备分配,子图计算等过程。

前端多语言编程环境与后端C/C++实现系统的通道归功于Swig的包装器。TensorFlow使用Bazel的构建工具,在编译之前启动Swig的代码生成过程,通过tf_session.i自动生成了两个适配(Wrapper)文件:

·        pywrap_tensorflow.py: 负责对接上层Python调用;

·        pywrap_tensorflow.cpp: 负责对接下层C实现。

此外,pywrap_tensorflow.py模块首次被加载时,自动地加载_pywrap_tensorflow.so的动态链接库。从而实现了pywrap_tensorflow.pypywrap_tensorflow.cpp的函数调用关系。

pywrap_tensorflow.cpp的实现中,静态注册了一个函数符号表。在运行时,按照Python的函数名称,匹配找到对应的C函数实现,最终转调到c_api.c的具体实现。

 (以上参考  TensorFlow架构与设计


阅读了 c_api.h 和 c_api.cc 的部分代码,这里附上一些对程序的标注及笔记

/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifndef TENSORFLOW_C_C_API_H_
#define TENSORFLOW_C_C_API_H_

#include <stddef.h>
#include <stdint.h>

// --------------------------------------------------------------------------
// C API for TensorFlow.
//
// The API leans towards simplicity and uniformity instead of convenience
// since most usage will be by language specific wrappers.
//
// Conventions:
// * We use the prefix TF_ for everything in the API.
// * Objects are always passed around as pointers to opaque structs
//   and these structs are allocated/deallocated via the API.
// * TF_Status holds error information.  It is an object type
//   and therefore is passed around as a pointer to an opaque
//   struct as mentioned above.
// * Every call that has a TF_Status* argument clears it on success
//   and fills it with error info on failure.
// * unsigned char is used for booleans (instead of the 'bool' type).
//   In C++ bool is a keyword while in C99 bool is a macro defined
//   in stdbool.h. It is possible for the two to be inconsistent.
//   For example, neither the C99 nor the C++11 standard force a byte
//   size on the bool type, so the macro defined in stdbool.h could
//   be inconsistent with the bool keyword in C++. Thus, the use
//   of stdbool.h is avoided and unsigned char is used instead.
// * size_t is used to represent byte sizes of objects that are
//   materialized in the address space of the calling process.
// * int is used as an index into arrays.
//
// Questions left to address:
// * Might at some point need a way for callers to provide their own Env.
// * Maybe add TF_TensorShape that encapsulates dimension info.
//
// Design decisions made:
// * Backing store for tensor memory has an associated deallocation
//   function.  This deallocation function will point to client code
//   for tensors populated by the client.  So the client can do things
//   like shadowing a numpy array.
// * We do not provide TF_OK since it is not strictly necessary and we
//   are not optimizing for convenience.
// * We make assumption that one session has one graph.  This should be
//   fine since we have the ability to run sub-graphs.
// * We could allow NULL for some arguments (e.g., NULL options arg).
//   However since convenience is not a primary goal, we don't do this.
// * Devices are not in this API.  Instead, they are created/used internally
//   and the API just provides high level controls over the number of
//   devices of each type.
//
// TensorFlow 的 C API
//
// API 倾向于简单性和统一性,而不是方便,因为大多数使用将由语言特定的包装器。
//
//公约:
// * API 中的所有内容都使用前缀 TF_ 。
// * 对象总是作为指向 opaque 结构体的指针传递,这些结构体通过 API 分配/释放。
// * TF_Status 保存错误信息。它是一个对象类型,因此如上所述作为指向不透明结构的指针传递。
// * 具有 TF_Status * 参数的每个调用都会成功清除,并在失败时填写错误信息。
// * unsigned char 用于布尔值(而不是 'bool' 类型)。在 C++ 中,bool 是一个关键字,而在 C99 中,bool 是在 stdbool.h 中定义的宏。两者可能不一致。例如,C99 和 C++ 11 标准都不强制 bool 类型的字节大小,因此在 stdbool.h 中定义的宏可能与 C++ 中的 bool 关键字不一致。因此,避免使用 stdbool.h,并且使用 unsigned char 代替。
// * size_t 用于表示在调用进程的地址空间中实现的对象的字节大小。
// * int 用作数组的索引。
//
//遗留问题:
// * 某些地方可能需要一种方式让调用者提供自己的环境。
// * 也许添加封装维度信息的 TF_TensorShape。
//
//设计决策:
// * 张量存储器的备份存储器具有相关的解除分配功能。此释放功能将指向由客户端填充的张量的客户端代码。所以客户端可以跟踪NumPy数组。
// * 我们不提供 TF_OK ,因为它不是严格必要的,为方便起见,我们没有进行优化。
// * 我们假设一个会话有一个图。这应该是正常的,因为我们有能力运行子图。
// * 我们可以为一些参数允许 NULL(例如,NULL 选项 arg)。但是,由于方便不是主要目标,我们不这样做。
// * 设备不在此 API 中。相反,它们在内部创建/使用,API 只是提供对每种类型的设备数量的高级控制。

#ifdef __cplusplus
extern "C" {
#endif
{ // TF_Version
// --------------------------------------------------------------------------
// TF_Version returns a string describing version information of the
// TensorFlow library. TensorFlow using semantic versioning.
// TF_Version 返回描述 TensorFlow 库的版本信息的字符串。 TensorFlow 使用语义版本控制。
extern const char* TF_Version();
}
{ // TF_DataType
// --------------------------------------------------------------------------
// TF_DataType holds the type for a scalar value.  E.g., one slot in a tensor.
// The enum values here are identical to corresponding values in types.proto.
// TF_DataType 保存标量值的类型。 例如张量中的一个 slot。
// 这里的枚举值与 types.proto 中的相应值相同。

typedef enum {
  TF_FLOAT = 1,
  TF_DOUBLE = 2,
  TF_INT32 = 3,  // Int32 tensors are always in 'host' memory.
  TF_UINT8 = 4,
  TF_INT16 = 5,
  TF_INT8 = 6,
  TF_STRING = 7,
  TF_COMPLEX64 = 8,  // Single-precision complex
  TF_COMPLEX = 8,    // Old identifier kept for API backwards compatibility
  TF_INT64 = 9,
  TF_BOOL = 10,
  TF_QINT8 = 11,     // Quantized int8
  TF_QUINT8 = 12,    // Quantized uint8
  TF_QINT32 = 13,    // Quantized int32
  TF_BFLOAT16 = 14,  // Float32 truncated to 16 bits.  Only for cast ops.
  TF_QINT16 = 15,    // Quantized int16
  TF_QUINT16 = 16,   // Quantized uint16
  TF_UINT16 = 17,
  TF_COMPLEX128 = 18,  // Double-precision complex
  TF_HALF = 19,
  TF_RESOURCE = 20,
} TF_DataType;

// TF_DataTypeSize returns the sizeof() for the underlying type corresponding
// to the given TF_DataType enum value. Returns 0 for variable length types
// (eg. TF_STRING) or on failure.
// TF_DataTypeSize 返回与给定 TF_DataType 枚举值对应的底层类型的 sizeof()。 
// 对于可变长度类型(例如 TF_STRING)或失败返回 0。
extern size_t TF_DataTypeSize(TF_DataType dt);
}
{// TF_Code
// --------------------------------------------------------------------------
// TF_Code holds an error code.  The enum values here are identical to
// corresponding values in error_codes.proto.
// TF_Code 保存错误代码。 这里的枚举值与 error_codes.proto 中的相应值相同。
typedef enum {
  TF_OK = 0,
  TF_CANCELLED = 1,
  TF_UNKNOWN = 2,
  TF_INVALID_ARGUMENT = 3,
  TF_DEADLINE_EXCEEDED = 4,
  TF_NOT_FOUND = 5,
  TF_ALREADY_EXISTS = 6,
  TF_PERMISSION_DENIED = 7,
  TF_UNAUTHENTICATED = 16,
  TF_RESOURCE_EXHAUSTED = 8,
  TF_FAILED_PRECONDITION = 9,
  TF_ABORTED = 10,
  TF_OUT_OF_RANGE = 11,
  TF_UNIMPLEMENTED = 12,
  TF_INTERNAL = 13,
  TF_UNAVAILABLE = 14,
  TF_DATA_LOSS = 15,
} TF_Code;
}
{ // TF_Status
// --------------------------------------------------------------------------
// TF_Status holds error information.  It either has an OK code, or
// else an error code with an associated error message.
// TF_Status 保存错误信息。 它有一个 OK 代码,或者一个带有相关错误消息的错误代码。
typedef struct TF_Status TF_Status;

// Return a new status object. 
// 返回一个新的状态对象。
extern TF_Status* TF_NewStatus();

// Delete a previously created status object.
// 删除以前创建的状态对象。
extern void TF_DeleteStatus(TF_Status*);

// Record <code, msg> in *s.  Any previous information is lost.
// A common use is to clear a status: TF_SetStatus(s, TF_OK, "");
// 在 *s 中的记录 <code,msg>。 任何以前的信息都会丢失。
// 常见的用法是清除状态:TF_SetStatus(s, TF_OK, "");
extern void TF_SetStatus(TF_Status* s, TF_Code code, const char* msg);

// Return the code record in *s.
// 返回 *s 中的记录代码。
extern TF_Code TF_GetCode(const TF_Status* s);

// Return a pointer to the (null-terminated) error message in *s.  The
// return value points to memory that is only usable until the next
// mutation to *s.  Always returns an empty string if TF_GetCode(s) is
// TF_OK.
// 返回 *s 中一个指向(空终止)错误消息的指针。
// 返回值指向直到下一个突变为 *s 之前才可用的内存。
// 如果TF_GetCode(TF)为TF_OK,则始终返回一个空字符串。
extern const char* TF_Message(const TF_Status* s);
}
{ // TF_Buffer
// --------------------------------------------------------------------------
// TF_Buffer holds a pointer to a block of data and its associated length.
// Typically, the data consists of a serialized protocol buffer, but other data
// may also be held in a buffer.
//
// By default, TF_Buffer itself does not do any memory management of the
// pointed-to block.  If need be, users of this struct should specify how to
// deallocate the block by setting the `data_deallocator` function pointer.

// TF_Buffer 保存指向一个数据块及其相关长度的指针。
// 通常,数据由序列化的 protocol buffer 组成,但其他数据也可以保存在 buffer 中。
//
// 默认情况下,TF_Buffer 本身不对指向块进行任何内存管理。
// 如果需要,该结构体的用户应该通过设置 `data_deallocator` 函数指针来指定如何释放该块。
typedef struct TF_Buffer {
  const void* data;
  size_t length;
  void (*data_deallocator)(void* data, size_t length);
} TF_Buffer;

// Makes a copy of the input and sets an appropriate deallocator.  Useful for
// passing in read-only, input protobufs.
// 备份输入并设置一个适当的 data_deallocator。 用于传递只读的输入 protobufs。
extern TF_Buffer* TF_NewBufferFromString(const void* proto, size_t proto_len);

// Useful for passing *out* a protobuf.
// 用于传递输出 protobufs。
extern TF_Buffer* TF_NewBuffer();

extern void TF_DeleteBuffer(TF_Buffer*);

extern TF_Buffer TF_GetBuffer(TF_Buffer* buffer);
}
{ // TF_Tensor
// --------------------------------------------------------------------------
// TF_Tensor holds a multi-dimensional array of elements of a single data type.
// For all types other than TF_STRING, the data buffer stores elements
// in row major order.  E.g. if data is treated as a vector of TF_DataType:
//
//   element 0:   index (0, ..., 0)
//   element 1:   index (0, ..., 1)
//   
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据引用\[1\]和引用\[2\],可以看出在代码中使用了Adafruit GFX库和Adafruit ST7735库。而根据问题中的错误提示"Adafruit_GFX.h: No such file or directory",说明编译器找不到Adafruit_GFX.h文件。这可能是因为你没有正确安装或导入Adafruit GFX库。 要解决这个问题,你需要确保已经正确安装了Adafruit GFX库。你可以通过以下步骤来安装库: 1. 打开Arduino IDE。 2. 在菜单栏中选择 "Sketch" -> "Include Library" -> "Manage Libraries"。 3. 在库管理器中,搜索 "Adafruit GFX"。 4. 找到 "Adafruit GFX Library" 并点击 "Install" 按钮进行安装。 安装完成后,你应该能够找到并包含Adafruit GFX库。 另外,还需要确保你已经正确导入了Adafruit GFX库和其他相关库,如引用\[2\]和引用\[3\]中所示。你可以在代码的开头添加以下代码来导入这些库: #include <Adafruit_GFX.h> #include <Adafruit_ST7735.h> #include <DHT.h> #include <SPI.h> #include <Wire.h> #include <Adafruit_SSD1306.h> 这样,编译器就能够找到所需的头文件并成功编译你的代码了。希望这能帮助你解决问题! #### 引用[.reference_title] - *1* *2* [合宙Air101 的LCD和按键怎么用Arudino IDE驱动](https://blog.csdn.net/u012388993/article/details/126819094)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [嵌入式学习笔记一个Arduino挂载DHT11温湿度传感器的实时温湿度显示](https://blog.csdn.net/weixin_48965625/article/details/121608798)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值