SIMD要求内存数据16字节对齐的问题

ylongwu 2013-08-26 11:12:44
SIMD要求处理的数据必须是16字节对齐的,请问普通情况下new的一个数组可以直接传递给simd的指针吗?

例如我先开辟一个普通的float型数组
float *buf = new float[100];

再用一个__m128的SIMD的指针来指向它
__m128 *p= (__m128*) buf;

因为new开辟的数组不一定是16字节对齐的,
请问这种指针传递方法有问题吗? 多谢了!
主要是后续的对这个指针的操作会不会出现问题?
...全文
928 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
ylongwu 2013-10-11
  • 打赏
  • 举报
回复
结贴,可以直接传递, 编译器会自动检查是否对齐,并调用相应的指令,对其和不对其有不同的执行,对齐的指令效率会高一些 开辟地址对齐的数组我现在使用的是 float *buf1 = reinterpret_cast<float*>(_aligned_malloc(sizeof(float)*dataLen, 32)); 32字节对齐 释放 _aligned_free(buf1);
赵4老师 2013-08-28
  • 打赏
  • 举报
回复
引用 7 楼 zhao4zhong1 的回复:
new开辟的数组一定是16字节对齐的。
纠正:new开辟的数组不一定是16字节对齐的。
menzi11 2013-08-28
  • 打赏
  • 举报
回复
介于曾经我也对这个问题头疼了半天,送楼主一个方法用吧:

template<typename T,int alignByte=随便啥字节对齐>
class AlignedAllocator
{
public:
	inline static T* Malloc(size_t size)
	{
		dbg_code(++counter);
		char *ptr,*ptr2,*aligned_ptr;

		ptr=new char[size*sizeof(T)+alignByte+sizeof(int)];

		ptr2 = ptr + sizeof(int);
		aligned_ptr = ptr2 + (alignByte - ((size_t)ptr2 & (alignByte-1) ));

		ptr2 = aligned_ptr - sizeof(int);
		*((int *)ptr2)=(int)(aligned_ptr - ptr);

		return(T*)(aligned_ptr);
	}
	inline static void Free(T* ptr)
	{
		int *ptr2=(int *)ptr - 1;
		char*const m=(char*)ptr - *ptr2;
		delete[] m;
	}
private:
	STACK_ONLY;
	ZTD_NO_COPYABLE(AlignedAllocator);
};
unituniverse2 2013-08-27
  • 打赏
  • 举报
回复
既然你用了C++,你要求的这种对齐需要一些变通的办法才能比较优雅的实现: __m128 *p = new __m128[count];//不管这个__m128是存放在哪里、用途是什么,好歹他对于编译器也只是各类型。这样做可以保证对齐。 如果实在受不了这种直接new,或者因为某些原因不能直接new,也可以用下面的办法: float * buf = new alignas(16) float [100]; __m128 *p= (__m128*) buf; 鉴于一些编译器还不支持alignas关键字, float * buf = (float *)new std::align_storage<sizeof(__m128), 16>::type [100 * sizeof(float) / sizeof(__m128)];//注意这一行需要根据使用场景调整,我不知道你具体的使用场景,所以暂时只能这样 __m128 *p= (__m128*) buf; 这样肯定是对齐的
kunkun2013 2013-08-26
  • 打赏
  • 举报
回复
32和64是地址总线长度,操作系统只是为了顺应它。 对齐的目的是为了优化地址取值操作,不会出现2次地址访问的问题。比如一个int跨了对齐地址界限,需要2次取值指令才能取出正确的数值。
kunkun2013 2013-08-26
  • 打赏
  • 举报
回复
引用 4 楼 ylongwu 的回复:
[quote=引用 3 楼 kunkun2013 的回复:] 如上所述。 32位,地址对齐是4,64位是8。 所以不确定是不是16,因为还没malloc出来。只能牺牲一点内存,来完成这个。或者自己实现个内存池,起始就是16对齐,比如用mmap,然后再里面进行16大小对齐分配。
这个32和64只跟操作系统的位数相关吧?我的系统是64为的 cpu也是64位的 这么说new出来的内存,是按8位对齐的,不过有50%的几率16位对齐[/quote] 这跟系统构架和编译器有关。一般都是8对齐。linux在ia64和x86-64是这个样子的,aix好像也是这样。对齐在c++上是2个语意决定的,default_align和max_align。default_align是数据分配的时候大小进行的对齐,max_align是地址对齐的值。这个还跟具体实现有关。你需要查看一下系统手册。 如果实在不想查,就malloc,100万次,只要分配出来的地址符合上面的公式那就ok。如果你想让代码跨平台,那就老老实实的按照上面的方法做。
ylongwu 2013-08-26
  • 打赏
  • 举报
回复
引用 3 楼 kunkun2013 的回复:
如上所述。 32位,地址对齐是4,64位是8。 所以不确定是不是16,因为还没malloc出来。只能牺牲一点内存,来完成这个。或者自己实现个内存池,起始就是16对齐,比如用mmap,然后再里面进行16大小对齐分配。
这个32和64只跟操作系统的位数相关吧?我的系统是64为的 cpu也是64位的 这么说new出来的内存,是按8位对齐的,不过有50%的几率16位对齐
kunkun2013 2013-08-26
  • 打赏
  • 举报
回复
如上所述。 32位,地址对齐是4,64位是8。 所以不确定是不是16,因为还没malloc出来。只能牺牲一点内存,来完成这个。或者自己实现个内存池,起始就是16对齐,比如用mmap,然后再里面进行16大小对齐分配。
ylongwu 2013-08-26
  • 打赏
  • 举报
回复
引用 1 楼 kunkun2013 的回复:
是地址对齐还是大小对齐? 大小:((size + (16 - 1)) & ~(16 - 1)) 地址比较麻烦,分配的时候多分配16字节,然后把地址按照上面的方式对齐。
地址对齐!
kunkun2013 2013-08-26
  • 打赏
  • 举报
回复
是地址对齐还是大小对齐? 大小:((size + (16 - 1)) & ~(16 - 1)) 地址比较麻烦,分配的时候多分配16字节,然后把地址按照上面的方式对齐。
unituniverse2 2013-08-26
  • 打赏
  • 举报
回复
单一变量默认就是对齐的: { int a; // 已对齐到int边界 long double f; // 已对齐到double边界 } auto p1 = new long long; // *p1已对齐到long long边界 auto p2 = new short; // *p2已对齐到short边界 结构体或类,默认是按各成员对齐单位的最小公倍数对齐的: struct tag1 // 已对齐到同时满足int和long double对齐的内存。 { int a; // 已对齐到int边界 long double f; // 已对齐到double边界 }; { tag obj1; //已对齐 } auto p3 = new tag;//已对齐 当然,结构体或类中有多个成员时,各成员的位置还可能会被调整来适应对齐: struct tag2 // 对齐到8字节边界 { WORD wVal1; // 已对齐到2字节边界(因为对齐到8字节边界即也满足了2字节边界的对齐) WORD wVal2; // 已对齐。但是为了满足dwVal3的对齐要求,在其后再追加4字节的空字节 INT64 dwVal3; // 已对齐(到8字节边界) }; 但是如果你加了#pragma pack(n),就可能有诺甘成员不满足对齐(仅限于成员默认的对齐数大于pack指定的n的成员),而且因为诺甘成员“不再需要”(你用了pack,编译器就以为你放弃了符合条件的成员的对齐请求)对齐,结构体的大小也可能会变得比没有pack修饰时的要小。
wenkai168 2013-08-26
  • 打赏
  • 举报
回复
我给你个正确可行以及确定的答案: 如果动态分配,用memalign分配 如果分在栈上,用__attritube__((aligned(16)))
赵4老师 2013-08-26
  • 打赏
  • 举报
回复
new开辟的数组一定是16字节对齐的。

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧