如何分配16字节的内存对齐数据(How to allocate 16byte memory alig

2019-06-25 13:44发布

我想实现在一块的代码,我需要我的一维数组是16字节的内存对齐SSE矢量化。 不过,我已经尝试了几种办法来分配16字节的内存对齐的数据,但它最终被4个字节的内存对齐。

我与英特尔编译器ICC工作。 这是一个示例代码,我与测试:

  #include <stdio.h>
  #include <stdlib.h>

  void error(char *str)
  {
   printf("Error:%s\n",str);
   exit(-1);
  }

  int main()
  {
   int i;
   //float *A=NULL;
   float *A = (float*) memalign(16,20*sizeof(float));

   //align
   // if (posix_memalign((void **)&A, 16, 20*sizeof(void*)) != 0)
   //   error("Cannot align");

    for(i = 0; i < 20; i++)
       printf("&A[%d] = %p\n",i,&A[i]);

        free(A);

         return 0;
   }

这是输出我得到:

 &A[0] = 0x11fe010
 &A[1] = 0x11fe014
 &A[2] = 0x11fe018
 &A[3] = 0x11fe01c
 &A[4] = 0x11fe020
 &A[5] = 0x11fe024
 &A[6] = 0x11fe028
 &A[7] = 0x11fe02c
 &A[8] = 0x11fe030
 &A[9] = 0x11fe034
 &A[10] = 0x11fe038
 &A[11] = 0x11fe03c
 &A[12] = 0x11fe040
 &A[13] = 0x11fe044
 &A[14] = 0x11fe048
 &A[15] = 0x11fe04c
 &A[16] = 0x11fe050
 &A[17] = 0x11fe054
 &A[18] = 0x11fe058
 &A[19] = 0x11fe05c

这是4字节对齐,每次,我都用了包括memalign,POSIX包括memalign。 因为我在Linux上工作,我不能用_mm_malloc无论是我可以用_aligned_malloc。 我得到了一个内存破坏错误,当我尝试(单独我认为这是适合GCC)使用_aligned_attribute。

任何人都可以帮助我准确地产生16字节的内存对齐数据在Linux平台上的icc。

Answer 1:

你分配的内存是对齐的16字节。 看到:
&A[0] = 0x11fe010
但是,在阵列float ,每个元素是4个字节,所以第二个是对齐的4字节。

可以使用的结构,每个包含单一的浮动,与阵列aligned属性:

struct x {
    float y;
} __attribute__((aligned(16)));
struct x *A = memalign(...);


Answer 2:

通过返回的地址memalign功能0x11fe010 ,这是一个多0x10 。 因此,功能是做了正确的事情。 这也意味着,你的阵列正常的16字节边界上对齐。 你在后面做的是打印类型的每一个元素的地址float的阵列英寸 由于float尺寸为你的情况正好是4字节,每一个地址将等于前一个+4。 例如, 0x11fe010 + 0x4 = 0x11FE014 。 当然,地址0x11FE014不是的倍数0x10 。 如果你要对齐16字节边界所有的花车,那么你将要浪费16 / 4 - 1每个元素的字节。 仔细检查您所使用的内在要求。



Answer 3:

据我所知,无论是memalignposix_memalign正在做他们的工作。

&A[0] = 0x11fe010

这是对齐到16字节。

&A[1] = 0x11fe014

当你&A[1]你告诉compiller到一个位置添加到float指针。 这难免会导致:

&A[0] + sizeof( float ) = 0x11fe010 + 4 = 0x11fe014

如果您打算让您的载体中的每一个元素对齐到16个字节,你应该考虑宣称是16字节宽结构的数组。

struct float_16byte
{
    float data;
    float padding[ 3 ];
}
    A[ ELEMENT_COUNT ];

然后,你必须分配内存ELEMENT_COUNT (20,在你的例子)变量:

struct float_16byte *A = ( struct float_16byte * )memalign( 16, ELEMENT_COUNT * sizeof( struct float_16byte ) );


Answer 4:

我发现这个代码在维基百科 :

Example: get a 12bit aligned 4KBytes buffer with malloc()

// unaligned pointer to large area
void *up=malloc((1<<13)-1);
// well aligned pointer to 4KBytes
void *ap=aligntonext(up,12);

where aligntonext() is meant as: 
move p to the right until next well aligned address if
not correct already. A possible implementation is

// PSEUDOCODE assumes uint32_t p,bits; for readability
// --- not typesafe, not side-effect safe
#define alignto(p,bits) (p>>bits<<bits)
#define aligntonext(p,bits) alignto((p+(1<<bits)-1),bits)


Answer 5:

我个人认为你的代码是正确的,适用于英特尔SSE代码。 当加载数据到XMM寄存器,相信处理器只能负载从主存储器4个连续的浮点数据与第一个16字节对齐的。

总之,我相信你做了什么是正是你想要的。



文章来源: How to allocate 16byte memory aligned data
标签: c memory sse icc