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 将不对齐,除非 widthcol 具有合适的值。理想情况下,widthcol 都应该是 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 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

Java 多线程 资源冲突

`-march` 和指令集开关之间会不会有冲突?

我有一个冲突矩阵,以及具有不同访问权限的用户列表,我想检查该用户是不是为冲突访问权限

写入位置0x00460000时发生访问冲突,这是啥原因?

随机内存访问和银行冲突

VS 2010 中的 C++ 调试访问冲突