我有一段 C 代码,如下所示:
for(int i = 0; i < numRows; i++) {
double *myRow = matrixPtr + (i * numCols);
for (int j = 0; j < numCols; j++) {
someOperation(myRow[j]);
}
}
matrixPtr
以行优先布局存储的 2D 矩阵在哪里。获取每行的引用/指针是为了使代码更具可读性,并避免需要为最内层循环(即matrixPtr[(i*numCols)+j]
)中的每次访问计算行偏移量。
在 Chapel 中,如果我要翻译上面的代码,并尝试将其紧密匹配,我可能会得到这样的结果:
for i in 0..numRows-1 {
ref myRow = matrix[i,..];
for j in 0..numCols-1 {
someOperation(myRow[j]);
}
}
其中matrix
是 Chapel 矩阵,myRow
是对矩阵行切片的引用。
我注意到,与省略数组切片步骤以获取行引用并直接访问matrix
by相比,上述 Chapel 代码的性能非常慢[i,j]
,我认为在编译器优化后与上面的 C 代码非常相似(实际上,其性能与上面的 C 代码几乎相同):
for i in 0..numRows-1 {
for j in 0..numCols-1 {
someOperation(matrix[i,j]);
}
}
我可以理解为什么它会变慢,因为您需要执行数组切片来获取每一行。但我想知道的是为什么 Chapel 中的数组切片要慢得多?首先,我的教堂体验充其量是很少的。
我试图查看生成的 C 代码以更好地了解正在发生的事情。我首先认为每次创建行引用时构建有界范围都会产生很多开销。为了测试这一点,我预先创建了范围并使用了它(即ref myRow = matrix[i,colRange]
)。但是,这似乎并没有改善运行时间。生成的 C 代码中唯一可以作为潜在线索隔离的另一部分是更改数组等级(或类似内容)的函数。
从角度来看,这种类型的矩阵运算在我的一个应用程序中执行了很多次,相比之下numRows
非常大和numCols
非常小,使用数组切片时 Chapel 代码的性能比直接访问矩阵慢 30-40 倍with [i,j]
(--fast
使用编译期间使用的标志)。
谢谢
更新:
这里有两个小程序,它们应该产生报告的减速(大约在 20 到 25 倍之间)并使用--fast
标志编译。direct.chpl 程序产生的执行时间与获取矩阵的 cPtr 然后计算行偏移量的版本相同,如上面的帖子中所述。
切片.chpl
use Time;
var numRows = 100000;
var numCols = 35;
var D : domain(2) = {0..numRows-1, 0..numCols-1};
var mat : [D] real;
mat = 1.0;
var totalTimer : Timer;
var accum : [0..numCols-1] real;
accum = 0.0;
totalTimer.start();
for i in 0..numRows-1 {
ref myRow = mat(i,..);
for j in 0..numCols-1 {
accum[j] += i * myRow[j];
}
}
totalTimer.stop();
writeln("Accum:");
writeln(accum);
writeln("\nTotal Elapsed time: ", totalTimer.elapsed(), " seconds");
直接.chpl:
use Time;
var numRows = 100000;
var numCols = 35;
var D : domain(2) = {0..numRows-1, 0..numCols-1};
var mat : [D] real;
mat = 1.0;
var totalTimer : Timer;
var accum : [0..numCols-1] real;
accum = 0.0;
totalTimer.start();
for i in 0..numRows-1 {
for j in 0..numCols-1 {
accum[j] += i * mat[i,j];
}
}
totalTimer.stop();
writeln("Accum:");
writeln(accum);
writeln("\nTotal Elapsed time: ", totalTimer.elapsed(), " seconds");
slices.chpl 的输出:
Accum:
4.99995e+09 4.99995e+09 4.99995e+09 4.99995e+09...
Total Elapsed time: 0.124494 seconds
direct.chpl 的输出:
Accum:
4.99995e+09 4.99995e+09 4.99995e+09 4.99995e+09...
Total Elapsed time: 0.005211 seconds
所以这似乎是运行时的 23 倍差异。这并不是我在实际应用程序中看到的 30-40 倍的差异,但肯定超出了我的预期。