c - 如何将 AVX/SIMD 与嵌套循环和 += 格式一起使用?

标签 c multithreading simd avx pagerank

我正在编写一个网页排名程序。我正在编写一种更新排名的方法。我已经成功地使用嵌套 for 循环和线程版本。但是我想改用 SIMD/AVX。

这是我想更改为 SIMD/AVX 实现的代码。

#define IDX(a, b) ((a * npages) + b)   // 2D matrix indexing
for (size_t i = 0; i < npages; i++) {
    temp[i] = 0.0;
    for (size_t j = 0; j < npages; j++) {
        temp[i] += P[j] * matrix_cap[IDX(i,j)];
    }
}

对于此代码,P[] 的大小为 npages,而 matrix_cap[] 的大小为 npages * npagesP[] 是页面的排名,temp[] 用于存储下一次迭代的页面排名,以便能够检查收敛。

我不知道如何用 AVX 解释 += 以及如何获取涉及两个大小为 npages 的数组/vector 和一个大小为矩阵的数据npages * npages(按行主要顺序)转换为可用于 SIMD/AVX 操作的格式。

就 AVX 而言,这是我目前所掌握的,尽管它非常非常不正确,只是对我大致想要做的事情的尝试。

ssize_t g_mod = npages - (npages % 4);
double* res = malloc(sizeof(double) * npages);
double sum = 0.0;
for (size_t i = 0; i < npages; i++) {
    for (size_t j = 0; j < mod; j += 4) {
        __m256d p = _mm256_loadu_pd(P + j);
        __m256d m = _mm256_loadu_pd(matrix_hat + i + j);
        __m256d pm = _mm256_mul_pd(p, m);
        _mm256_storeu_pd(&res + j, pm);
        for (size_t k = 0; k < 4; k++) {
            sum += res[j + k];
        }
    }
    for (size_t i = mod; i < npages; i++) {
        for (size_t j = 0; j < npages; j++) {
            sum += P[j] * matrix_cap[IDX(i,j)];
        }
    }
    temp[i] = sum;
    sum = 0.0;
}

如何格式化我的数据,以便我可以对其使用 AVX/SIMD 操作(加、乘)来优化它,因为它会被大量调用。

最佳答案

考虑对最内层循环使用 OpenMP4.x #pragma omp simd reduction。请记住,omp 缩减不适用于 C++ 数组,因此您必须使用如下所示的临时缩减变量。

#define IDX(a, b) ((a * npages) + b)   // 2D matrix indexing
for (size_t i = 0; i < npages; i++) {
    my_type tmp_reduction = 0.0; // was: // temp[i] = 0.0;
    #pragma omp simd reduction (+:tmp_reduction)
    for (size_t j = 0; j < npages; j++) {
        tmp_reduction += P[j] * matrix_cap[IDX(i,j)];
    }
    temp[i] = tmp_reduction;
}

对于 x86 平台,最新的 GCC (4.9+) 和英特尔编译器目前支持 OpenMP4.x。一些 LLVM 和 PGI 编译器也可能支持它。

附言自动-矢量化(“自动”意味着编译器在没有任何编译指示的情况下进行矢量化,即没有来自开发人员的明确指导)可能有时适用于某些编译器变体(尽管这不太可能,因为数组元素作为缩减变量)。但是,严格来说自动向量化此代码是不正确的。您必须使用显式 SIMD pragma 来“解决”减少依赖性并(作为一个好的副作用)消除指针歧义(以防通过指针访问数组)。

关于c - 如何将 AVX/SIMD 与嵌套循环和 += 格式一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37524711/

相关文章:

c++ - C++ 中的 Clang vector 扩展和相等运算符

iphone - 在iPhone上读取5000行文本文件

c - wsprintf 将我限制为 1024 个字符?

c - strcmp 输出之谜 - strcmp 实际上是如何比较字符串的?

Python:选择或轮询 threading.event

c - 互斥线程 - 代码似乎无法正确退出

c - 程序只能在 Debug模式下运行,但不能在正常的 exe 中运行(使用 c lion)?

java - 尽管很忙,但我的后台服务被杀死并等待了很长时间才重新启动

c# - 为什么与小阵列相比,大阵列的C#SIMD的性能增益较低?

alignment - aarch64 上未对齐 SIMD 加载/存储的性能