我有两个用于进行矩阵乘法的内核,一个使用全局内存,第二个内核使用常量内存。我想使用Cuda分析器来测试两个内核的速度。
我在1.3设备和2.0设备上都进行了测试。由于在这些设备上使用缓存作为全局内存,我期望内核具有恒定内存以便在1.3设备上更快并且全局内存内核在2.0设备上更快但我发现在两个设备中全局内存内核是比较快的。这是由于内存在全局内存上的合并吗?如果是这样有一种方法可以使常量内核更快?
我使用80x80的矩阵和16的块大小。
这是全局内存内核
__global__ void MatMulGlobKernel(const Matriz A, const Matriz B, Matriz C) {
float Cvalor = 0;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
if(fil > A.height || col > B.width) return;
for (int e = 0; e < A.width; ++e)
Cvalor += A.valores[row * A.width + e] * B.valores[e * B.width + col];
C.valores[row * C.width + col] = Cvalor;
}
A.valores,B.valores和C.valores居于全球记忆中。
现在这里是常量内存内核。
__global__ void MatMulConstKernel(const Matriz A, const Matriz B, Matriz C) {
float Cvalor = 0;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
if(fil > A.height || col > B.width) return;
for (int e = 0; e < A.width; ++e)
Cvalor += A_const_valores[row * A.width + e] * B_const_valores[e * B.width + col];
C.valores[row * C.width + col] = Cvalor;
}
A_const_valores和B_const_valores驻留在常量内存中,而C.valores驻留在全局内存中。
这是1.3设备(Tesla M1060)的分析器结果
Const内核101.70us
全局内核51.424us
和2.0设备(GTX 650)
Const内核178.05us
全球内核58.144us
答案 0 :(得分:1)
矩阵乘法通常有一些组件,其中相邻线程正在从内存中访问相邻值。您的内核具有以这种方式运行的负载:
B.valores[e * B.width + col];
从全局内存中读取时,可以在一个周期内(从L1或L2缓存)向warp提供此负载。是的,这是一个合并的负载。
另一方面,常量存储器每个周期只能提供一个32位数量。因此,常量高速缓存将需要32个周期才能将相同的请求数据传递给warp。
这不是常量内存的典型用例。当 warp中的每个线程请求内存中的相同位置时,最好使用常量内存。
作为一项实验,您可能会看到如果将A
矩阵保留在__constant__
内存中并将B
矩阵保留在全局内存中,您可能会得到什么样的结果。
但是,如果您真的想要快速矩阵乘法,请使用CUBLAS。