c++ - 三角矩阵转换和自动并行化

标签 c++ optimization compiler-optimization icc

我在 ICC 中玩了一下自动并行化(11.1;旧的,但对此无能为力),我想知道为什么编译器不能并行化内部循环以进行简单的高斯消除:

void makeTriangular(float **matrix, float *vector, int n) {
    for (int pivot = 0; pivot < n - 1; pivot++) {
        // swap row so that the row with the largest value is
        // at pivot position for numerical stability
        int swapPos = findPivot(matrix, pivot, n);
        std::swap(matrix[pivot], matrix[swapPos]);
        std::swap(vector[pivot], vector[swapPos]);
        float pivotVal = matrix[pivot][pivot];
        for (int row = pivot + 1; row < n; row++) { // line 72; should be parallelized
            float tmp = matrix[row][pivot] / pivotVal;  
            for (int col = pivot + 1; col < n; col++) { // line 74
                matrix[row][col] -= matrix[pivot][col] * tmp;
            }
            vector[row] -= vector[pivot] * tmp;
        }
    }
}

我们只写入依赖于私有(private)行(和列)变量的数组,并且行保证大于枢轴,因此对于编译器来说应该很明显我们没有覆盖任何内容。

我正在使用-O3 -fno-alias -parallel -par-report3进行编译,并获得大量依赖项ala:假设矩阵行75和矩阵行73之间存在FLOW依赖关系。假定矩阵行 73 和矩阵行 75 之间的 ANTI 依赖性。 并且仅对第 75 行相同。编译器有什么问题?显然我可以准确地告诉它如何处理一些编译指示,但我想了解编译器可以单独得到什么。

最佳答案

基本上,编译器无法确定不存在依赖关系,因为名称 matrix 和名称 vector 都被读取和写入(即使使用不同的地区)。您也许可以通过以下方式解决这个问题(虽然有点脏):

void makeTriangular(float **matrix, float *vector, int n)
{     
    for (int pivot = 0; pivot < n - 1; pivot++) 
    {         
         // swap row so that the row with the largest value is    
         // at pivot position for numerical stability       
         int swapPos = findPivot(matrix, pivot, n);    
         std::swap(matrix[pivot], matrix[swapPos]);   
         std::swap(vector[pivot], vector[swapPos]);     
         float pivotVal = matrix[pivot][pivot];     
         float **matrixForWriting = matrix;  // COPY THE POINTER
         float *vectorForWriting = vector;   // COPY THE POINTER
         // (then parallelize this next for loop as you were)
         for (int row = pivot + 1; row < n; row++)  { 
              float tmp = matrix[row][pivot] / pivotVal;               
              for (int col = pivot + 1; col < n; col++) {
                  // WRITE TO THE matrixForWriting VERSION
                  matrixForWriting[row][col] = matrix[row][col] - matrix[pivot][col] * tmp; 
              } 
              // WRITE TO THE vectorForWriting VERSION
              vectorForWriting[row] = vector[row] - vector[pivot] * tmp; 
         } 
    }
} 

底线只是给你正在写入的内容一个临时不同的名称来欺骗编译器。我知道这有点肮脏并且我一般不会推荐这种编程。但如果您确定没有数据依赖性,那就完全没问题了。

事实上,我会在它周围添加一些注释,对于 future 看到此代码的人来说,这是一种解决方法,以及为什么要这样做。

编辑:我认为这个答案基本上是由@FPK 触及的,并且答案是由@Evgeny Kluev 发布的。然而,在 @Evgeny Kluev 的回答中,他建议将此作为输入参数,这可能会并行化,但不会给出正确的值,因为矩阵中的条目不会更新。我认为我上面发布的代码也会给出正确的答案。

关于c++ - 三角矩阵转换和自动并行化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10349940/

相关文章:

c++ - 在 C++ 中捕获 lambda 的全局引用是否会抑制别名优化?

java - 如果常量会阻止使用字符串参数,优化器是否会阻止创建字符串参数?

opengl - 如何确定我的 GLSL 编译器是否优化了以下内容?

c++ - 如何将 char 数组的多个元素与一个十六进制值进行比较?

c++ - 二维 vector 给出分割错误

mysql - 每个连接的计数 - 优化

mysql - 高效获取两列总和最高的 25 行 (MySQL)

c++ - 以毫秒为单位的本地时间

c++ - 多包含 .h 文件

MYSQl 使用评论优化博客文章表