我正在开发一个GTX泰坦X GPU,CUDA 8.0和驱动程序版本367.48的系统。当我使用nvidia-smi
时,我的GPU是正确列出的。
我正在使用下面的代码来执行Pi的数值逼近,并测量代码的执行时间5000次。但是,内核返回0.0作为近似结果。为什么会发生这种情况?
#include "cuda_runtime.h"
#include <stdio.h>
#define ITERATIONS 96000000
const int threads = 256;
// Synchronous error checking call. Enable with nvcc -DEBUG
inline void checkCUDAError(const char *fileName, const int line)
{
#ifdef DEBUG
cudaThreadSynchronize();
cudaError_t error = cudaGetLastError();
if(error != cudaSuccess)
{
printf("Error at %s: line %i: %s\n", fileName, line, cudaGetErrorString(error));
exit(-1);
}
#endif
}
__global__ void integrateSimple(float *sum)
{
__shared__ float ssums[threads];
// Each thread computes its own sum.
int global_idx = threadIdx.x + blockIdx.x * blockDim.x;
if(global_idx < ITERATIONS)
{
float step = 1.0f / ITERATIONS;
float x = (global_idx + 0.5f) * step;
ssums[threadIdx.x] = 4.0f / (1.0f + x * x);
}
else
{
ssums[threadIdx.x] = 0.0f;
}
// The 1st thread will gather all sums from all other threads of this block into one
__syncthreads();
if(threadIdx.x == 0)
{
float local_sum = 0.0f;
for(int i = 0; i < threads; ++i)
{
local_sum += ssums[i];
}
sum[blockIdx.x] = local_sum;
}
}
int main()
{
const float PI = 3.14159265358979323846264;
int deviceCount = 0;
printf("Starting...");
cudaError_t error = cudaGetDeviceCount(&deviceCount);
if (error != cudaSuccess)
{
printf("cudaGetDeviceCount returned %d\n-> %s\n", (int)error, cudaGetErrorString(error));
return 1;
}
deviceCount == 0 ? printf("There are no available CUDA device(s)\n") : printf("%d CUDA Capable device(s) detected\n", deviceCount);
/*--------- Simple Kernel ---------*/
int blocks = (ITERATIONS + threads - 1) / threads;
float *sum_d;
float step = 1.0f / ITERATIONS;
for (int i = 0; i < 5000; ++i)
{
// Allocate device memory
cudaMallocManaged((void **)&sum_d, blocks * sizeof(float));
// CUDA events needed to measure execution time
cudaEvent_t start, stop;
float gpuTime;
// Start timer
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, 0);
/*printf("\nCalculating Pi using simple GPU kernel over %i intervals...\n", (int)ITERATIONS);*/
integrateSimple<<<blocks, threads>>>(sum_d);
cudaDeviceSynchronize(); // wait until the kernel execution is completed
checkCUDAError(__FILE__, __LINE__);
// Stop timer
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&gpuTime, start, stop);
// Sum result on host
float piSimple = 0.0f;
for (int i = 0; i < blocks; i++)
{
piSimple += sum_d[i];
}
piSimple *= step;
cudaFree(sum_d);
// Stop timer
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&gpuTime, start, stop);
// Print execution times
/*printf("\n======================================\n\n");*/
printf("%.23lf,%.23lf,%f", piSimple, fabs(piSimple - PI), gpuTime/1000);
printf("\n");
}
// Reset Device
cudaDeviceReset();
return 0;
}
最后一行的输出
0.00000000000000000000000,3.14159274101257324218750,0.000009 0.00000000000000000000000,3.14159274101257324218750,0.000009 0.00000000000000000000000,3.14159274101257324218750,0.000009 0.00000000000000000000000,3.14159274101257324218750,0.000008 0.00000000000000000000000,3.14159274101257324218750,0.000008 0.00000000000000000000000,3.14159274101257324218750,0.000008
另外,当我编译得到这个警告时:
nvcc警告:“计算20”、“sm 20”和“sm_21”体系结构是>不推荐的,并可能在以后的版本中删除(使用-Wno-废弃-gpu-目标来抑制警告)。
发布于 2021-03-01 03:57:29
你的具体案例
这可能只是您实际上根本没有检查错误:当您没有使用#ifdef
显式编译时,您的错误检查函数有它的代码-DDEBUG‘ed-away。
此外,正如@AnderBiguri建议的那样,确保您正在为正确的微体系结构( nvcc --gpucode/--gencode/--gpu-architecture
开关)进行编译。
一般问题
当内核似乎产生0值的输出时,您应该:
确保你在检查错误
您应该使用CUDA现代-C++ API包装器 (警告:我是作者,所以我有偏见),在这里所有API调用后面都是检查是否成功;或者您应该在CUDA调用之后手动添加错误检查。注意:如果您已经编写了自己的错误处理代码,请确保它能够被触发并打印出来(例如,将cudaSuccess以外的内容传递给它)。
区分“输出零”和“什么都不做”
尝试用一个初始模式填充您的输出缓冲区,以查看是否有任何东西被写入它们(例如,从包含类似cudaMemcpy()
的0xDEADBEEF
的缓冲区中写入的)。然后,通过检查输出,可以确定内核是否实际写入0值。如果它写0,那么你需要调试你的内核。否则..。
确保内核实际上已启动
如果您的内核没有向输出写入任何内容,那么:
第一个选项是最有可能的,实际上它与第二个选项大致相同,只是错误发生在启动之前。重复检查和三次检查错误处理代码。
然后,使用NSight计算或NSight系统分析器来查看内核是否实际启动和执行。如果是的话,那么它又回到了调试阶段。尝试使用精心放置的printf()
指令或实际调试器工具。
https://stackoverflow.com/questions/66420924
复制