【问题标题】:access violation _mm_store_si128 SSE Intrinsics访问冲突_mm_store_si128 SSE Intrinsics
【发布时间】:2017-07-03 22:41:10
【问题描述】:

我想在 8 位灰度图像中创建垂直梯度直方图。 可以指定计算梯度的垂直距离。 我已经设法使用 Intrinsics 加速了我的代码的另一部分,但它在这里不起作用。 如果 _mm_store_si128 被注释掉,代码将毫无例外地运行。 如果没有评论,我会遇到访问冲突。

这里出了什么问题?

#define _mm_absdiff_epu8(a,b) _mm_adds_epu8(_mm_subs_epu8(a, b), _mm_subs_epu8(b, a)) //from opencv
void CreateAbsDiffHistogramUnmanaged(void* source, unsigned int sourcestride, unsigned int height, unsigned int verticalDistance, unsigned int histogram[])
{
unsigned int xcount = sourcestride / 16;
__m128i absdiffData;
unsigned char* bytes = (unsigned char*) _aligned_malloc(16, 16);
__m128i* absdiffresult = (__m128i*) bytes;
__m128i* sourceM = (__m128i*) source;
__m128i* sourceVOffset = (__m128i*)source + verticalDistance * sourcestride;

for (unsigned int y = 0; y < (height - verticalDistance); y++)
{
    for (unsigned int x = 0; x < xcount; x++, ++sourceM, ++sourceVOffset)
    {
        absdiffData = _mm_absdiff_epu8(*sourceM, *sourceVOffset);
        _mm_store_si128(absdiffresult, absdiffData);
        //unroll loop
        histogram[bytes[0]]++;
        histogram[bytes[1]]++;
        histogram[bytes[2]]++;
        histogram[bytes[3]]++;
        histogram[bytes[4]]++;
        histogram[bytes[5]]++;
        histogram[bytes[6]]++;
        histogram[bytes[7]]++;
        histogram[bytes[8]]++;
        histogram[bytes[9]]++;
        histogram[bytes[10]]++;
        histogram[bytes[11]]++;
        histogram[bytes[12]]++;
        histogram[bytes[13]]++;
        histogram[bytes[14]]++;
        histogram[bytes[15]]++;
    }
}
_aligned_free(bytes);
}

【问题讨论】:

    标签: c++ x86 simd sse intrinsics


    【解决方案1】:

    您的函数在加载时崩溃,因为输入数据未正确对齐。为了解决这个问题,你必须改变你的代码:

    absdiffData = _mm_absdiff_epu8(*sourceM, *sourceVOffset);
    

    到:

    absdiffData = _mm_absdiff_epu8(_mm_loadu_si128(sourceM), _mm_loadu_si128(sourceVOffset));
    

    这里我使用非对齐加载。

    附:我在Simd Library 中实现了类似的功能(SimdAbsSecondDerivativeHistogram)。它有SSE2AVX2NEONAltivec 实现。希望对你有帮助。

    附言另外我强烈建议检查这一行:

    __m128i* sourceVOffset = (__m128i*)source + verticalDistance * sourcestride);
    

    这可能会导致崩溃(访问输入数组边界之外的内存)。也许你想到了这个:

    __m128i* sourceVOffset = (__m128i*)((char*)source + verticalDistance * sourcestride);
    

    【讨论】:

    • 非常感谢您的帮助。我尝试了您的改进,但错误仍然存​​在。此外,我知道输入数据是对齐的,因为我正在对同一数据执行其他操作。
    • @JosefBauer 你检查函数 _aligned_malloc() 的结果吗?因为我在这段代码中没有任何异常。
    • 这一行还有一个额外的错误:__m128i* sourceVOffset = (__m128i*)source + verticalDistance * sourcestride; 必须更改为 __m128i* sourceVOffset = (__m128i*) ((unsigned char*) source + (verticalDistance * sourcestride)); @ErmIg 你是对的,我也必须更改为 __mm_loadu_si128。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    • 2016-06-25
    • 2016-09-11
    • 1970-01-01
    相关资源
    最近更新 更多