Intel® FPGA SDK for OpenCL™ Pro Edition: 最佳实践实践指南

ID 683521
日期 9/26/2022
Public
文档目录

4.5. 使用/不使用填充来对齐结构体

正确的对齐结构体有助于 Intel® FPGA SDK for OpenCL™ Offline Compiler生成最高效的硬件。
正确的struct(结构体)对齐意味着该对齐可以被平均分成struct大小。
重要: 请确保数据结构的4字节对齐。小于4个字节的struct对齐会导致硬件较大也更慢。硬件效率随着对齐的增加而增加。如下实例中,Pixel_s结构仅1字节对齐,但是Pixel结构是4字节对齐,由于存在一个4字节not_used整数:
typedef struct {
	char r,g,b,alpha;
} Pixel_s;

typedef union {
     Pixel_s p;
     int not_used;
} Pixel;
您还可以使用aligned属性强制4字节对齐,如以下示例代码中所示:
typedef struct {
       char r,g,b,alpha;
} __attribute__((aligned(4))) Pixel;

离线编译器符合ISO C标准,该标准要求struct对齐必须满足以下所有标准:

  • 该对齐必须是所有struct成员对齐之间最小公倍数的整数倍。
  • 对齐必须是2的幂。

您可以将aligned(N)属性包含在内核代码中来设置struct对齐。如果没有对齐属性,离线编译器根据struct的大小来确定struct的数组中每个struct的对齐。请参考以下实例:

__kernel void test (struct mystruct* A,
                    struct mystruct* B)
{
    A[get_global_id(0)] = B[get_global_id(0)];
}

如果mystruct的大小是101字节,则每个加载或存储访问都是1字节对齐。如果mystruct是128字节,则每个加载或存储访问就是128字节对齐,这样就生成最高效的硬件。

struct内的结构体字段未对齐时,则离线编译器插入填充以将它们对齐。在struct字段之间插入填充会以如下方式影响硬件效率:

  • 增加结构体的大小
  • 可能影响对齐

要防止离线编译器插入填充,请在内核代码中包含packed属性。上述ISO C标准在确定打包或解包struct的对齐时适用。请参考以下实例:

struct mystruct1
{
    char a;
    int b;
};

mystruct1的大小是8字节。因此,struct为8字节对齐,从而实现内核中的高效访问。现在请考虑另一个实例:

struct mystruct2
{
    char a;
    int b;
    int c;
};

mystruct2的大小是12字节,并且struct是4字节对齐。因为结构体字段被填充,所以结构体未对齐,内核中的访问效率低下。

以下是struct中包含packed属性的实例:

struct __attribute__((packed)) mystruct3
{
    char a;
    int b;
    int c;
};

mystruct3的大小是16字节。因为mystruct3已对齐,并且struct字段之间无填充,因而该内核中的访问比mystruct3中的访问更有效。

要在结构体中同时包含aligned(N)packed属性,请参考以下实例:

struct __attribute__((packed)) __attribute__((aligned(16))) mystruct5
{
    char a;
    int b;
    int c;
};

mystruct5的大小为9字节。因为aligned(16)属性,struct被存储在阵列中的16字节对齐地址。由于mystruct5为16字节对齐并且无填充,该内核中的访问效率高。

有关struct对齐以及aligned(N)packed属性的更多信息,请参阅以下文档:

  • OpenCL Specification version 1.2的第6.11.1小节。
  • Intel® FPGA SDK for OpenCL™ 编程指南数据结构填充的禁用插入小节
  • Intel® FPGA SDK for OpenCL™ 编程指南指定结构体的对齐部分