可移植 C++ 编程¶
注意:本文档涵盖了需要构建和执行的代码 以硬件环境为目标。这适用于核心执行运行时,因为 以及此 repo 中的内核和后端实现。这些规则不会 必须适用于仅在开发主机上运行的代码,例如 authoring 或构建工具。
ExecuTorch 运行时代码旨在实现可移植性,并且应该为 各种系统,从服务器到移动电话再到 DSP,从 POSIX 到 Windows 到裸机环境。
这意味着它不能假定存在:
文件
线程
异常
stdout
,stderr
printf()
,fprintf()
POSIX API 和概念概述
它也不能假设:
64 位指针
给定整数类型的大小
的标志
char
将二进制大小保持在最小,并保持对内存的严格控制 allocation,则代码不能使用:
malloc()
,free()
new
,delete
大多数类型;尤其是管理自己的容器类型 内存(如 AND )或内存管理包装器类型(如 AND )。
stdlibc++
string
vector
unique_ptr
shared_ptr
为了帮助降低复杂性,代码可能不依赖于任何外部 依赖项除外:
flatbuffers
(用于文件反序列化).pte
flatcc
(用于事件跟踪序列化)Core PyTorch(仅适用于 ATen 模式)
平台抽象层 (PAL)¶
为避免承担目标系统的功能,ExecuTorch 运行时
允许客户端覆盖其平台抽象层中的低级函数
(PAL),用于执行操作
喜欢://executorch/runtime/platform/platform.h
获取当前时间戳
打印日志消息
使系统出现紧急情况
内存分配¶
运行时代码应分配内存,而不是使用 or
使用 ()
由客户提供。malloc()
new
MemoryManager
//executorch/runtime/executor/memory_manager.h
文件加载¶
客户端不应直接加载文件,而应为数据提供缓冲区
已加载,或包装在类似 .DataLoader
整数类型¶
ExecuTorch 运行时代码不应假设 primitive 的大小
类型如 、 、 或 。例如,仅 C++ 标准
保证宽度至少为 16 位。ARM 工具链被视为未签名,而其他工具链通常将其视为已签名。int
short
char
int
char
相反,运行时 API 使用一组更可预测但仍然是标准的 整数类型:
<cstdint>
类型如 , ;这些类型保证了位 width 和 signness,无论架构如何。在以下情况下使用这些类型 需要一个非常具体的整数宽度。uint64_t
int32_t
size_t
用于事物计数或内存偏移量。 保证 大到足以表示任何内存字节偏移量;即,它将与 目标系统的本机指针类型。更喜欢使用它而不是 counts/offsets,这样 32 位系统就不需要为 64 位值的不必要开销。size_t
uint64_t
ssize_t
对于某些 ATen 兼容性情况,其中返回 signed count 的 Count。尽可能选择。Tensor
size_t
浮点运算¶
并非每个系统都支持浮点运算:有些系统甚至不启用
浮点仿真。因此,核心运行时代码
不得在运行时执行任何浮点运算,尽管可以
只需创建或管理 OR 值(例如,在 an 中)。float
double
EValue
内核在核心运行时之外,允许执行浮点运算 算术。尽管某些内核可能选择不这样做,以便它们可以在系统上运行 不支持浮点数。
伐木¶
ExecuTorch 运行时不使用 、 、 、 或 或 等库,而是提供 中的接口和 中的接口。消息是使用 PAL 中的钩子打印的,
这意味着客户端可以将它们重定向到任何底层日志记录系统,或者
如果可用,只需将它们打印出来。printf()
fprintf()
cout
cerr
folly::logging
glog
ET_LOG
//executorch/runtime/platform/log.h
ET_CHECK
//executorch/runtime/platform/assert.h
stderr
日志记录格式可移植性¶
固定宽度整数¶
当您有像
int64_t value;
ET_LOG(Error, "Value %??? is bad", value);
你应该为零件放什么来匹配 ?在不同
systems,则 typdef 可能是 、 、 或 。
选择格式(如 、 或 可能适用于一个目标),但会中断
在其他方面。%???
int64_t
int64_t
int
long int
long long int
%d
%ld
%lld
为了便于移植,运行时代码使用了标准的(但不可否认很尴尬)
来自 的帮助程序宏。每个可移植整数类型都有相应的宏,例如<cinttypes>
PRIn##
int32_t
->PRId32
uint32_t
->PRIu32
int64_t
->PRId64
uint64_t
->PRIu64
有关详细信息,请参阅 https://en.cppreference.com/w/cpp/header/cinttypes
这些宏是文本字符串,可以与 format 字符串,例如
int64_t value;
ET_LOG(Error, "Value %" PRId64 " is bad", value);
请注意,这需要将文本格式字符串(额外的 double
引号)。它还需要在宏之前使用前导。%
但是,通过使用这些宏,可以保证工具链将使用 适合类型的格式模式。
铸造¶
有时,尤其是在跨越 ATen 和 lean 模式的代码中,该 值本身可能因 build 模式而异。在这些情况下,将 值设置为 Lean 模式类型,例如:
ET_CHECK_MSG(
input.dim() == output.dim(),
"input.dim() %zd not equal to output.dim() %zd",
(ssize_t)input.dim(),
(ssize_t)output.dim());
在这种情况下,返回 lean 模式,而返回 ATen 模式。由于它们在概念上都是
return (signed) counts)是最合适的整数类型。 可以工作,但它不必要地需要 32 位系统来处理
在 Lean 模式下具有 64 位值。Tensor::dim()
ssize_t
at::Tensor::dim()
int64_t
ssize_t
int64_t
这是唯一需要强制转换的情况,当 lean 和 ATen 模式不同意。否则,请使用与类型匹配的格式模式。