【问题标题】:SSE access violationSSE 访问冲突
【发布时间】: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)

【问题讨论】:

    标签: x86 sse simd


    【解决方案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);?
    猜你喜欢
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    • 2017-05-06
    • 2013-02-26
    • 2015-04-23
    相关资源
    最近更新 更多