SSE 访问冲突
Posted
技术标签:
【中文标题】SSE 访问冲突【英文标题】:SSE access violation 【发布时间】:2010-08-03 08:24:33 【问题描述】:我有代码:
float *mu_x_ptr;
__m128 *tmp;
__m128 *mm_mu_x;
mu_x_ptr = _aligned_malloc(4*sizeof(float), 16);
mm_mu_x = (__m128*) mu_x_ptr;
for(row = 0; row < ker_size; row++)
tmp = (__m128*) &original[row*width + col];
*mm_mu_x = _mm_add_ps(*tmp, *mm_mu_x);
从这里我得到:
First-chance exception at 0x00ad192e in SSIM.exe: 0xC0000005: Access violation reading location 0x00000000.
Unhandled exception at 0x00ad192e in SSIM.exe: 0xC0000005: Access violation reading location 0x00000000.
The program '[4452] SSIM.exe: Native' has exited with code -1073741819 (0xc0000005)
运行程序时,_mm_add_ps 行出现错误。
原始分配使用 _aligned_malloc(..., 16);以及传递给函数,所以就我对 sse 的理解而言,它不应该是未对齐的。
我想知道是否有人知道为什么会崩溃,因为我不明白为什么。
编辑:宽度和 col 始终是 4 的倍数。col 是 0 或 4,而 width 始终是 4 的倍数。
EDIT2:看起来我的原始数组未对齐。不会:
function(float *original);
.
.
.
orignal = _aligned_malloc(width*height*sizeof(float), 16);
function(original);
_aligned_free(original);
确保原件在函数内部对齐?
Edit3:这真的很奇怪。当我这样做时:
float *orig;
orig = _aligned_malloc(width*height*sizeof(float), 16);
assert(isAligned(orig));
断言失败
#define isAligned(p) (((unsigned long)(p)) & 15 == 0)
【问题讨论】:
【参考方案1】:我认为你需要使用
__m128 tmp = _mm_load_ps( &original[row * width + col] );
而不是
tmp = (__m128 *)&original[row * width + col];
编辑:如果您在某个偏移量之后遇到访问冲突错误,那么您的步幅可能未对齐。无论哪种方式分配 __m128 个元素(代表 4 个浮点数)。这负责对齐。
您还可以通过消除算术 [row * width + col] 来获得一些额外的性能。 确定您的步幅并相应地增加您的指针。
【讨论】:
做到了。我的步伐很慢,所以现在我在四个像素和四个像素上进行操作。关于增加我的指针的提示也将实现。 奇怪,实际上使用算术比增加指针快很多。 这确实很奇怪。你是在增加一个常数吗?【参考方案2】:tmp
将不对齐,除非 width
和 col
具有合适的值。理想情况下,width
和 col
都应该是 4 的倍数。
您可能想要添加一些断言来检查对齐方式,例如
#define IsAligned(p) ((((unsigned long)(p)) & 15) == 0)
float *mu_x_ptr;
__m128 *tmp;
__m128 *mm_mu_x;
assert(original != NULL && IsAligned(original));
mu_x_ptr = _aligned_malloc(4 * sizeof(float), 16);
assert(mu_x_ptr != NULL && IsAligned(mu_x_ptr));
mm_mu_x = (__m128 *)mu_x_ptr;
assert(IsAligned(mm_mu_x));
for (row = 0; row < ker_size; row++)
tmp = (__m128 *)&original[row * width + col];
assert(IsAligned(tmp));
*mm_mu_x = _mm_add_ps(*tmp, *mm_mu_x);
【讨论】:
对不起,忘了说。 col 是 0 或 4,width 总是 4 的倍数。现在编辑它。 抱歉 - 我们的编辑发生冲突 - 我正在修复格式等 - 您可能想再次添加有关 col 和 width 的部分。 哦,是的 - 错过了。现在在我上面的回答中添加了进一步的建议。 嗯...获取数据后失败。因此,对齐必须是错误的。但不会 _aligned_malloc(widthheightsizeof(float), 16);分配对齐的内存,然后我只需将原始正常传递给函数,这样函数就可以是:function(float *original);?以上是关于SSE 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章