我想实现在一块的代码,我需要我的一维数组是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。
你分配的内存是对齐的16字节。 看到:
&A[0] = 0x11fe010
但是,在阵列float
,每个元素是4个字节,所以第二个是对齐的4字节。
可以使用的结构,每个包含单一的浮动,与阵列aligned
属性:
struct x {
float y;
} __attribute__((aligned(16)));
struct x *A = memalign(...);
通过返回的地址memalign
功能0x11fe010
,这是一个多0x10
。 因此,功能是做了正确的事情。 这也意味着,你的阵列正常的16字节边界上对齐。 你在后面做的是打印类型的每一个元素的地址float
的阵列英寸 由于float
尺寸为你的情况正好是4字节,每一个地址将等于前一个+4。 例如, 0x11fe010 + 0x4 = 0x11FE014
。 当然,地址0x11FE014
不是的倍数0x10
。 如果你要对齐16字节边界所有的花车,那么你将要浪费16 / 4 - 1
每个元素的字节。 仔细检查您所使用的内在要求。
据我所知,无论是memalign
和posix_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 ) );
我发现这个代码在维基百科 :
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)
我个人认为你的代码是正确的,适用于英特尔SSE代码。 当加载数据到XMM寄存器,相信处理器只能负载从主存储器4个连续的浮点数据与第一个16字节对齐的。
总之,我相信你做了什么是正是你想要的。