【发布时间】:2012-04-27 11:38:04
【问题描述】:
我在 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;
}
}
}
我们只写入依赖于私有行(和 col)变量的数组,并且行保证大于枢轴,因此编译器应该很明显我们没有覆盖任何内容。
我正在使用-O3 -fno-alias -parallel -par-report3 进行编译,并获得了很多依赖项ala:assumed FLOW dependence between matrix line 75 and matrix line 73. 或assumed ANTI dependence between matrix line 73 and matrix line 75.,仅第75 行也是如此。编译器有什么问题?显然,我可以准确地告诉它如何处理一些 pragma,但我想了解编译器可以单独获得什么。
【问题讨论】:
-
对我来说,似乎编译器尝试并行化此代码时,它不仅考虑内存位置,还考虑寄存器机器的位置。我不是“编译器”:)。非常深刻的问题。
-
@parallelgeek 不是真的。循环迭代之间的内存依赖是一个问题的原因是因为并行化会改变这种情况下的语义(例如,我是否在另一个线程写入值之前/之后读取)。每个核心都有自己的寄存器集,所以这不是问题。
-
可能是因为内部循环没有“完美嵌套”?我只是好奇! :) 我看不到任何真正的依赖关系,在更新尾随子矩阵行的情况下限制并行化。但是编译器可能对不完全适合的嵌套更加保守。 :)
-
@parallel 也不确定 icc 如何并行化事物,所以这个问题基本上是一个尝试找出答案 :) 哦,好吧,几百个代表赏金应该尽快帮助事情。
-
你真正的任务是什么?为什么要讨论这个例子?您只是想为不同的代码挖掘编译器的东西,还是需要优化这个?也许等离子(MAGMA)库适合?
标签: c++ optimization compiler-optimization icc