数据访问方面的元素智能对齐要求,以便在英特尔® MIC 架构上符合 ABI 规范

面向英特尔® MIC 架构的编译器方法

IA-32 和英特尔® 64 架构不同英特尔® MIC 架构要求所有数据访问要根据其大小正确对齐否则程序可能会发生异常。例如,一个需要四个存储字节的整数变量必须要在一个是 4 的倍数的地址上进行分配。同样对于需要八个存储字节的双精度浮点变量或指针变量来说也必须要在一个是 8 的倍数的地址上进行分配。结构和联合假定其对齐要求最高的组件已经对齐。每个成员被分配一个最小的偏移量(以实现相应的对齐)。任意对象的大小一直是对象对齐的倍数。

请注意删除 IA-32 和英特尔® 64 架构上没有对齐的访问通过调整相应的源代码也有助于提高性能。

1. 以下是一个 Fortran 实例,它不符合英特尔® MIC 架构上的 ABI 规范 请注意在对象内部使用序列关键字。

考虑以下结构:

    type, public :: GridEdge_t

        sequence

        integer :: head_face ! needed if head vertex has shape (i.e. square)

        integer :: tail_face ! needed if tail vertex has shape (i.e. square)

        integer :: head_ind !

        integer :: tail_ind !

        type (GridVertex_t),pointer :: head ! edge head vertex

        type (GridVertex_t),pointer :: tail ! edge tail vertex

        logical :: reverse

    end type GridEdge_t

将单独字段的体积相加此对象的大小为 36 字节。由于使用了序列关键字,因此其可在内存中保持连续。如果我们有一个这样的对象数组,那么无须增加大小即可对数组元素进行封装。所以在第一个元素之后,后面的元素在试图访问字段头或字段尾时再无法对齐。根据 ABI 的要求字段头和字段尾应保持 8 字节对齐因此 GridEdge_t 应是 8 个字节 sizeof GridEdge_t 应是 8 的倍数viz. 40。如果删除 SEQUENCE 关键字,编译器会自动创建带有 40 个字节的 GridEdge_t

2. 下面这个简单的示例为 C 中不符合 ABI 的情况

#include <malloc.h>

int main(int argc, char **argv)

{

    char *blob = (char *)malloc(100); // malloc returns 8-byte aligned pointer

    float *ptr = (float *)(blob + argc); // Assume program is invoked with no arguments, argc=1

 

    for (int i = 0; i < argc; i++) {

        ptr[i] = 0; // GP fault here since floating point data is not aligned at 4-bytes

    }

    return 0;

}

用户编写的内存分配例程可能会发生这种不符合访问要求的情况。用户一般不会编写其内存访问例程,这会在无意中导致分配内存无法对齐的情况。由于不满足英特尔® MIC 架构上的 ABI 要求,这可能会引起运行时错误,用户应通过调整源代码来解决此问题。

使用 C C++) 中的 "#pragma pack" 也会导致不符合 ABI 规范的情况。

 

Pour de plus amples informations sur les optimisations de compilation, consultez notre Avertissement concernant les optimisations.