我正在尝试在一段代码上实现SSE向量化,我需要将1D数组与16字节内存对齐。但是,我已经尝试了几种方法来分配16字节内存对齐数据,但它最终是4字节内存对齐。
我必须使用Intel 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。 当我尝试使用_aligned_attribute(我认为它仅适用于gcc)时,我收到内存损坏错误。
任何人都可以协助我在linux平台上为icc准确生成16字节内存对齐数据。
答案 0 :(得分:14)
您分配的内存是16字节对齐的。请参阅:
&A[0] = 0x11fe010
但是在float
的数组中,每个元素是4个字节,所以第二个是4字节对齐。
您可以使用一个结构数组,每个结构包含一个浮点数,并带有aligned
属性:
struct x {
float y;
} __attribute__((aligned(16)));
struct x *A = memalign(...);
答案 1 :(得分:7)
memalign
函数返回的地址为0x11fe010
,是0x10
的倍数。所以功能正在做正确的事情。这也意味着您的数组 在16字节边界上正确对齐。稍后您要做的是在数组中打印类型float
的每个下一个元素的地址。由于float
大小恰好是4个字节,因此每个下一个地址将等于前一个地址+4。例如,0x11fe010 + 0x4 = 0x11FE014
。当然,地址0x11FE014
不是0x10
的倍数。如果要在16字节边界上对齐所有浮点数,则每个元素必须浪费16 / 4 - 1
个字节。仔细检查您正在使用的内在函数的要求。
答案 2 :(得分:1)
AFAIK,memalign
和posix_memalign
正在开展工作。
&A[0] = 0x11fe010
这与16字节对齐。
&A[1] = 0x11fe014
执行&A[1]
时,您告诉编译器将一个位置添加到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 ) );
答案 3 :(得分:0)
我在Wikipedia上找到了这段代码:
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)
答案 4 :(得分:0)
我个人认为您的代码是正确的,适用于英特尔SSE代码。当您将数据加载到XMM寄存器时,我相信处理器只能从主存储器加载4个连续的浮点数据,第一个浮点数据对齐16个字节。
简而言之,我相信你所做的正是你想要的。
答案 5 :(得分:0)
您也可以在VS中使用它。
__declspec(align(16)) struct x {
long long a;
long long b;
char c;
};
代替此
struct x {
float y;
} __attribute__((aligned(16)));