【发布时间】:2014-06-27 17:45:36
【问题描述】:
为什么编译器不做一些可以在内核中完成的琐碎优化?我有以下矩阵乘法代码:
__global__ void matrixMultiply(float * A, float * B, float * C,
int numARows, int numAColumns,
int numBRows, int numBColumns,
int numCRows, int numCColumns) {
int n=numAColumns;
int Row=blockIdx.x*blockDim.x+threadIdx.x;
int Col=blockIdx.y*blockDim.y+threadIdx.y;
if((Row<numCRows) && (Col<numCColumns)){
for(int k=0;k<n;++k){
C[Row*numCColumns+Col]+=
A[Row*numAColumns+k]*B[k*numBColumns+Col];
}
}
}
如果我使用时间寄存器Cvalue 来存储总和,该示例会更快:
__global__ void matrixMultiply(float * A, float * B, float * C,
int numARows, int numAColumns,
int numBRows, int numBColumns,
int numCRows, int numCColumns) {
int n=numAColumns;
int Row=blockIdx.x*blockDim.x+threadIdx.x;
int Col=blockIdx.y*blockDim.y+threadIdx.y;
if((Row<numCRows) && (Col<numCColumns)){
float Cvalue=0;
for(int k=0;k<n;++k){
Cvalue+=A[Row*numAColumns+k]*B[k*numBColumns+Col];
}
C[Row*numCColumns+Col]=Cvalue;
}
}
在最后一种情况下,C 的全局内存只被访问一次,而在第一种情况下,它在循环中被多次访问。这种优化通常不是由编译器完成的吗?在我的测试中,这两个代码的性能差异大约为 30%,我正在做 nvcc -O3 ...
【问题讨论】:
-
代码不一样。我想你想要
C[Row*numCColumns+Col]+=而不是C[Row*numCColumns+Col]=。 -
对不起,是的...我更正了。
-
由于C在计算过程中可能被不同的线程访问,所以代码会不一样。
-
在第一个例子中你也没有将 C 归零。
-
@Dave:由于没有障碍,其他线程可能会做什么是无关紧要的。真正的问题是
C可能与A或B重叠(或与矩阵相同),这使得这两个例程非常不同。
标签: c optimization compiler-construction nvcc