对齐和未对齐加载和存储SSE向量 - 如何减少代码重复?

5 c++ sse simd

我经常被迫编写两个使用SSE指令的函数实现,因为输入和输出缓冲区可能有对齐或未对齐的地址:

void some_function_aligned(const float * src, size_t size, float * dst)
{
    for(size_t i = 0; i < size; i += 4)
    {
        __m128 a = _mm_load_ps(src + i);
        // do something...
        _mm_store_ps(dst + i, a);
    }
}
Run Code Online (Sandbox Code Playgroud)

void some_function_unaligned(const float * src, size_t size, float * dst)
{
    for(size_t i = 0; i < size; i += 4)
    {
        __m128 a = _mm_loadu_ps(src + i);
        // do something...
        _mm_storeu_ps(dst + i, a);
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个问题:如何减少代码重复,因为这些功能几乎相同?

Erm*_*mIg 5

这个问题有一个解决方案,在这里广泛使用(http://simd.sourceforge.net/).它基于用于加载和保存SSE向量的模板函数的特化:

template <bool align> __m128 load(const float * p);

template <> inline __m128 load<false>(const float * p)
{
    return _mm_loadu_ps(p); 
}

template <> inline __m128 load<true>(const float * p)
{
    return _mm_load_ps(p); 
}

template <bool align> void store(float  * p, __m128 a);

template <> inline void Store<false>(float  * p, __m128 a)
{
    _mm_storeu_ps(p, a);
}

template <> inline void Store<true>(float  * p, __m128 a)
{
    _mm_store_ps(p, a);
}
Run Code Online (Sandbox Code Playgroud)

现在我们只能编写一个模板函数的实现:

template <bool align> void some_function(const float * src, size_t size, float * dst)
{
    for(size_t i = 0; i < size; i += 4)
    {
        __m128 a = load<align>(src + i);
        // do something...
        store<align>(dst + i, a);
    }
}
Run Code Online (Sandbox Code Playgroud)