cuda - CUDA 中的响应时间问题为什么 cpu 比 gpu 快?
问题描述
嗨,我的时间响应有问题我在 GPU 上的响应时间比 CPU 上的响应时间更长,使用的算法是矩阵乘法算法
使用下一个功能:
// Start timers
cudaEvent_t timer1, timer2;
cudaEventCreate(&timer1);
cudaEventCreate(&timer2);
cudaEventRecord(timer1, 0);
cudaEventSynchronize(timer1);
// Stop timers
cudaEventRecord(timer2, 0);
cudaEventSynchronize(timer1);
cudaEventSynchronize(timer2);
float elapsed;
cudaEventElapsedTime(&elapsed, timer1, timer2);
cudaDeviceReset();
return elapsed;
这是我在 GPU 上的代码:
float Mult_gpu(float* hostPtr, float* hostPtr2, float* hostPtr3, int size, int Ncols, int Nrows, int n) {
size_t pitch;
check("Creating timers");
cudaEvent_t timer1, timer2;
cudaEventCreate(&timer1);
cudaEventCreate(&timer2);
cudaEventRecord(timer1, 0);
cudaEventSynchronize(timer1);
/******************************************/
/***Configuracion de las matrices en gpu***/
/******************************************/
float* devPtr;
cudaMallocPitch(&devPtr, &pitch, n * sizeof(float), Nrows);
cudaMemcpy2D(devPtr, pitch, hostPtr, n * sizeof(float), n * sizeof(float), Nrows, cudaMemcpyHostToDevice);
float* devPtr2;
cudaMallocPitch(&devPtr2, &pitch, Ncols * sizeof(float), n);
cudaMemcpy2D(devPtr2, pitch, hostPtr2, Ncols * sizeof(float), Ncols * sizeof(float), n, cudaMemcpyHostToDevice);
float* devPtr3;
cudaMallocPitch(&devPtr3, &pitch, Ncols * sizeof(float), Nrows);
//dim3 gridSize(iDivUp(Ncols3, BLOCKSIZE_x), iDivUp(Nrows3, BLOCKSIZE_y));
//dim3 blockSize(BLOCKSIZE_y, BLOCKSIZE_x);
dim3 block(32, 32); //hilos por bloque
dim3 grid((size / block.x) + 1, (size / block.y) + 1); //numero de bloques
/**************************/
/**Lanzamiento del kernel**/
/**************************/
Mult << <grid, block >> > (devPtr, devPtr2, devPtr3, pitch, Ncols, Nrows, n);
cudaDeviceSynchronize();
/*********************************/
/***Copiado de devPtr a hosPtr2***/
/*********************************/
cudaMemcpy2D(hostPtr3, Ncols * sizeof(float), devPtr3, pitch, Ncols * sizeof(float), Nrows, cudaMemcpyDeviceToHost);
//cudaMemcpy(hostPtr3, devPtr3, size * sizeof(float), cudaMemcpyDeviceToHost);
cudaFree(devPtr);
cudaFree(devPtr2);
cudaFree(devPtr3);
// Stop timers
cudaEventRecord(timer2, 0);
cudaEventSynchronize(timer1);
cudaEventSynchronize(timer2);
float elapsed;
cudaEventElapsedTime(&elapsed, timer1, timer2);
cudaDeviceReset();
return elapsed;
}
这是我在 CPU 上的代码
float Mult_cpu(float* hostPtrA, float* HostPtrB, float* hostPtrC, int Ncols, int Nrows, int n)
{
cudaEvent_t timer1, timer2;
cudaEventCreate(&timer1);
cudaEventCreate(&timer2);
cudaEventRecord(timer1, 0);
cudaEventSynchronize(timer1);
for (int i = 0; i < Nrows; ++i) {
for (int j = 0; j < Ncols; ++j) {
float suma = 0;
for (int k = 0; k < n; ++k) {
suma += hostPtrA[i * n + k] * HostPtrB[k * Ncols + j];
}
hostPtrC[i * Ncols + j] = suma;
}
}
// Stop timers
cudaEventRecord(timer2, 0);
cudaEventSynchronize(timer1);
cudaEventSynchronize(timer2);
float elapsed;
cudaEventElapsedTime(&elapsed, timer1, timer2);
return elapsed;
}
当我使用矩阵 500x500 或任何矩阵时,CPU 比 GPU 快,我不明白为什么我不知道问题是我的内核程序还是我使用的 CUDA 函数
我的内核代码
__global__ void Mult(float* devPtrA, float* devPtrB, float* devPtrC, size_t pitch, int Ncols, int Nrows, int n)
{
float temp;
int r = blockDim.y * blockIdx.y + threadIdx.y; //for (int f = 0; f <= fil - 1; f += 1) equivalencia en for
int c = blockDim.x * blockIdx.x + threadIdx.x; //for (int c = 0; c <= col - 1; c += 1)
if ((r < Ncols) && (c < Nrows)) {
for (int c2 = 0; c2 < n; c2++) {
float* vertical = (float*)((char*)devPtrA + r * pitch);
float element1 = vertical[c2];
float* horizontal = (float*)((char*)devPtrB + c2 * pitch);
float element2 = horizontal[c];
temp += element1 * element2;
}
//printf("\nla fila es: %d la columna es: %d el valor es: %8.4f\n\n", r, c, temp);
float* vertical2 = (float*)((char*)devPtrC + r * pitch);
vertical2[c] = temp;
}
}
解决方案
您应该阅读SIMT 架构、CUDA 执行模型和分支分歧的概念。使用分析器分析您的 CUDA 内核性能。我怀疑if ((r < Ncols) && (c < Nrows))
内核中的条件会导致每个扭曲中的线程发散,从而降低性能。还会pitch
影响代码中的全局内存访问模式,这是影响 CUDA 内核性能的另一个因素。可以在此处找到其他一些出色的优化技巧。
推荐阅读
- python - python3目标的Jenkins作业失败
- npm - 如何在 Github 操作中指定节点的路径?
- android - 用户选择时将应用程序降级到较低的 versionCode
- vue.js - 增加 v-data-table Vuetify 中标题的字体大小
- c - 从任何基数转换为小数和区分大小写
- c# - PDFium,pdf中提取的图像损坏但渲染时没有问题
- javascript - javascript 代码不返回任何内容(nan/emptystring/no 问题)有什么问题?
- python - 如何使用 tweepy python 模块仅流式传输 LIST 时间线的状态?
- javascript - 如何从其他 json 文件内部加载 json 文件?
- google-cloud-http-load-balancer - GCP 后端服务更新