c++ - 将SSE矩阵 vector 乘法代码转换为AVX

标签 c++ sse simd avx avx2

我正在尝试将 SSE 函数转换为 AVX。该函数执行 vector 矩阵乘法,这是我的工作 SSE 代码:

void multiply_matrix_by_vector_SSE(float* m, float* v, float* result, unsigned const int vector_dims)
{
    size_t i, j;
    for (i = 0; i < vector_dims; ++i)
    {
        __m128 acc = _mm_setzero_ps();
        for (j = 0; j < vector_dims; j += 4)
        {
            __m128 vec = _mm_load_ps(&v[j]);
            __m128 mat = _mm_load_ps(&m[j + vector_dims * i]);
            //acc = _mm_add_ps(acc, _mm_mul_ps(mat, vec));
            acc = _mm_fmadd_ps(mat, vec, acc);
        }
        acc = _mm_hadd_ps(acc, acc);
        acc = _mm_hadd_ps(acc, acc);
        _mm_store_ss(&result[i], acc);
    }
}

以下是我对 AVX 的看法:

void multiply_matrix_by_vector_AVX(float* m, float* v, float* result, unsigned const int vector_dims)
{
    size_t i, j;

    for (i = 0; i < vector_dims; ++i)
    {
        __m256 acc = _mm256_setzero_ps();
        for (j = 0; j < vector_dims; j += 8)
        {
            __m256 vec = _mm256_load_ps(&v[j]);
            __m256 mat = _mm256_load_ps(&m[j + vector_dims * i]);
            acc = _mm256_fmadd_ps(mat, vec, acc);
        }
        acc = _mm256_hadd_ps(acc, acc);
        acc = _mm256_hadd_ps(acc, acc);
        acc = _mm256_hadd_ps(acc, acc);
        acc = _mm256_hadd_ps(acc, acc);

        _mm256_store_ps(&result[i], acc);
    }
}

但是,AVX 代码崩溃(访问冲突读取位置 0xFFFFFFFFFFFFFFFF)。


有人可以帮助我让我的 AVX 功能正常工作吗?

PS:我在函数中传递的矩阵和 vector 的大小始终是 8 的倍数。此外,我传递给 SSE 函数的数组是 16 位对齐的 (__declspec(align(16))float * =generate_matrix(256);) 并且我传递给 AVX 函数的数组是 32 位对齐的 (__declspec(align(32))float* =generate_matrix(256);) ;

最佳答案

不幸的是,使用这样的水平添加并不会轻易扩展到 256 位,因为指令(以及大多数其他指令)是“laned”的 - 它的作用就像两个并行的 haddps,一个位于上半部分和下半部分各有一个,没有混合,因此下半部分和上半部分不会相加。

此外,当然,它仍然不是打包结果,并且该打包存储有一个对齐存储写入某个未对齐地址并且会失败(该错误有点奇怪,但无论如何)。

无论如何,让我们修复水平总和:(未测试)

// this part still works
acc = _mm256_hadd_ps(acc, acc);
acc = _mm256_hadd_ps(acc, acc);
// this is new
__m128 acc1 = _mm256_extractf128_ps(acc, 0);
__m128 acc2 = _mm256_extractf128_ps(acc, 1);
acc1 = _mm_add_ss(acc1, acc2);
// do scalar store, obviously
_mm_store_ss(&result[i], acc1);

顺便说一下,内部循环需要 10 个独立的链(和 10 个累加器)才能最大化 Haswell 的吞吐量。

关于c++ - 将SSE矩阵 vector 乘法代码转换为AVX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33845931/

相关文章:

Calc atan2 与 NEON

python - Pygraphviz 安装失败,错误代码为 1083 无法打开文件 graphviz/cgraph.h : No such file or directory

c++ - 用 sse 累加整数 vector

c++ - 我的编译器在做什么? (优化memcpy)

linux - gcc 4.x 不支持 x87​​ FPU 数学?

c++ - 使用 SIMD 范例在 256 位 vector 上应用给定函数

SIMD与矢量架构

c++ - "T t = {};"和 "T t{};"可以产生不同的结果吗?

c++ - GCC 问题 - 从 'void (*)(MyObject*, bool)' 到 'const void*' 的无效转换