目录
第一个程序:用GPU输出Hello World
写一个CUDA C程序步骤
-
用专用扩展名.cu来创建一个源文件
-
使用CUDA nvcc编译器来编译程序
-
从命令行运行可执行文件,这个文件有可在GPU上运行的内核代码
hello.cu
#include "../common/common.h"
#include <stdio.h>
/*
* A simple introduction to programming in CUDA. This program prints "Hello
* World from GPU! from 10 CUDA threads running on the GPU.
*/
__global__ void helloFromGPU()
{
printf("Hello World from GPU!\n");
}
int main(int argc, char **argv)
{
printf("Hello World from CPU!\n");
helloFromGPU<<<1, 10>>>();
CHECK(cudaDeviceReset());
return 0;
}
编译
nvcc hello.cu -o hello
运行
./hello
cudaDeviceReset()函数是用来显示的释放和清空当前进程中于当前设备有关的所有资源当重置函数移除后 编译运行则只输出hello world from cpu,printf在gpu上被调用,cudaDeviceReset()函数使这些来自gpu的输出发送到主机,然后在控制台输出。没有调用cudaDeviceReset()函数就不能保证这些可以被显示
关于cudaDeviceReset(); 这句话如果没有,则不能正常的运行,因为这句话包含了隐式同步,GPU和CPU执行程序是异步的,核函数调用后成立刻会到主机线程继续,而不管GPU端核函数是否执行完毕,所以上面的程序就是GPU刚开始执行,CPU已经退出程序了,所以我们要等GPU执行完了,再退出主机线程。
common.h
#include <sys/time.h>
#include <cuda_runtime.h>
#include <stdio.h>
#ifndef _COMMON_H
#define _COMMON_H
cudaError_t ErrorCheck(cudaError_t status,const char* filename,int lineNumber)
{
if(status != cudaSuccess)
{
printf("CUDA API error: \r\ncode=%d, name=%s, description=%s\r\nfile=%s, line=%d\r\n",
status,cudaGetErrorName(status),cudaGetErrorString(status),filename,lineNumber
);
}
return status;
}
#define CHECK(call) \
{ \
const cudaError_t error = call; \
if (error != cudaSuccess) \
{ \
fprintf(stderr, "Error: %s:%d, ", __FILE__, __LINE__); \
fprintf(stderr, "code: %d, reason: %s\n", error, \
cudaGetErrorString(error)); \
exit(1); \
} \
}
#define CHECK_CUBLAS(call) \
{ \
cublasStatus_t err; \
if ((err = (call)) != CUBLAS_STATUS_SUCCESS) \
{ \
fprintf(stderr, "Got CUBLAS error %d at %s:%d\n", err, __FILE__, \
__LINE__); \
exit(1); \
} \
}
#define CHECK_CUR