GPU(CUDA)学习日记(三)------ CUDA基本架构介绍以及编程入门!~~
来源:互联网 发布:塑料瓶盖螺纹编程 编辑:程序博客网 时间:2024/05/17 00:05
首先,介绍CUDA的架构:在CUDA架构下,线程的最小单元是thread,多个thread组成一个block,多个block再组成一个grid,不同block之间的thread不能读写同一shared memory共享内存,因此,block里面的thread之间的通信和同步所带来的开销是比较大的。SM以 32 个 Thread 为一组的 Warp 来执行 Thread。Warp内的线程是静态的,即在属于同一个warp内的thread之间进行通信,不需要进行栅栏同步(barrier)。Fermi的设计根据G80和GT200的架构作出的很多缺陷来改变。在Fermi中,每个SM中的数量不再是GT200的8个SP,而是变成了32个SP,NVIDIA现在又称之为CUDA Core,总共具有16个SM,所以总共有512个SP。而在GT200中,是30个SM,240个SP。
其次,介绍CUDA的初始化:首先,先建立一个档案 first_cuda.cu。如果是使用 Visual Studio 的话,则请先按照这里的设定方式设定 project。要使用 runtime API 的时候,需要 include cuda_runtime.h。所以,在程序的最前面,加上
#include <stdio.h>
#include <cuda_runtime.h>
接下来是一个 InitCUDA 函式,会呼叫 runtime API 中,有关初始化 CUDA 的功能:
bool InitCUDA()
{
int count;
cudaGetDeviceCount(&count);
if(count == 0)
{
fprintf(stderr, "There is no device.\n");
return false;
}
int i;
for(i = 0; i < count; i++)
{
cudaDeviceProp prop;
if(cudaGetDeviceProperties(&prop, i) == cudaSuccess)
{
if(prop.major >= 1)
{
break;
}
}
}
if(i == count)
{
fprintf(stderr, "There is no device supporting CUDA 1.x.\n");
return false;
}
cudaSetDevice(i);
return true;
}
这个函式会先呼叫 cudaGetDeviceCount 函式,取得支持 CUDA 的装置的数目。如果系统上没有支持 CUDA 的装置,则它会传回 1,而 device 0 会是一个仿真的装置,但不支持 CUDA 1.0 以上的功能。所以,要确定系统上是否有支持 CUDA 的装置,需要对每个 device 呼叫cudaGetDeviceProperties 函式,取得装置的各项数据,并判断装置支持的 CUDA 版本(prop.major 和 prop.minor 分别代表装置支持的版本号码,例如 1.0 则 prop.major 为 1 而prop.minor 为 0)。
nvcc 是 CUDA 的 compile 工具,它会将 .cu 檔拆解出在 GPU 上执行的部份,及在 host 上执行的部份,并呼叫适当的程序进行 compile 动作。在 GPU 执行的部份会透过 NVIDIA 提供的 compiler 编译成中介码,而 host 执行的部份则会透过系统上的 C++ compiler 编译(在Windows 上使用 Visual C++ 而在 Linux 上使用 gcc)。
最后,来看一个例子,这个例子对于我来说很有帮助!
在主函数中,
int* gpudata, *result; clock_t* time;
cudaMalloc((void**) &gpudata, sizeof(int) * DATA_SIZE); // 此句子用来开辟GPU的空间;
cudaMalloc((void**) &result, sizeof(int) * THREAD_NUM * BLOCK_NUM);
cudaMalloc((void**) &time, sizeof(clock_t) * BLOCK_NUM * 2); //此句为定义了一个CUDA提供的计算时间的方法,新手忽略~
cudaMemcpy(gpudata, data, sizeof(int) * DATA_SIZE, cudaMemcpyHostToDevice);
//此句用来将数据data以gpudata的名字送入GPU中,其中cudaMemcpyHostToDevice表示从CPU传入GPU;
sumOfSquares<<<BLOCK_NUM, THREAD_NUM, 0>>>(gpudata, result, time);
int sum[THREAD_NUM * BLOCK_NUM]; clock_t time_used[BLOCK_NUM * 2];
cudaMemcpy(&sum, result, sizeof(int) * THREAD_NUM * BLOCK_NUM, cudaMemcpyDeviceToHost);
cudaMemcpy(&time_used, time, sizeof(clock_t) * BLOCK_NUM * 2, cudaMemcpyDeviceToHost);
cudaFree(gpudata);
cudaFree(result);
cudaFree(time);
int final_sum = 0;
for(int i = 0; i < THREAD_NUM * BLOCK_NUM; i++)
{
final_sum += sum[i];
}
clock_t min_start, max_end;
min_start = time_used[0];
max_end = time_used[BLOCK_NUM];
for(int i = 1; i < BLOCK_NUM; i++)
{
if(min_start > time_used[i]) min_start = time_used[i];
if(max_end < time_used[i + BLOCK_NUM]) max_end = time_used[i + BLOCK_NUM];}
printf("sum: %d time: %d\n", final_sum, max_end - min_start);
这个程序例子中,主要的东西是主函数中的调用方法,具体要做的是:
1、定义一个内存指针,并为自己将要传到GPU函数中的变量开辟一个空间(cudaMalloc());
2、利用cudaMemcpy()将数据从CPU中传到GPU中;
3、定义内核函数,注意内核函数的调用方式以及获得线程序号的方法~
- GPU(CUDA)学习日记(三)------ CUDA基本架构介绍以及编程入门!~~
- GPU(CUDA)学习日记(三)------ CUDA基本架构介绍以及编程入门!~~
- GPU(CUDA)学习日记(十二)------ CUDA并行编程较有用的总结
- GPU(CUDA)学习日记(十二)------ CUDA并行编程较有用的总结
- GPU(CUDA)学习日记(九)------ CUDA存储器模型
- GPU(CUDA)学习日记(十三)------ CUDA内存简介
- GPU(CUDA)学习日记(九)------ CUDA存储器模型
- GPU(CUDA)学习日记(十三)------ CUDA内存简介
- GPU(CUDA)学习日记(九)------ CUDA存储器模型
- GPU(CUDA)学习日记(十三)------ CUDA内存简介
- GPU(CUDA)学习日记(十四)------CUDA软件更新信息 Parallel Nsight 3.0新特性以及NVAPI介绍
- GPU(CUDA)学习日记(十四)------CUDA软件更新信息 Parallel Nsight 3.0新特性以及NVAPI介绍
- 《GPU高性能编程CUDA实战》学习笔记(三)
- GPU(CUDA)学习日记(八)------ Parallel Nsight2.2调试; CUDA:no source correspandence for breakpoint以及nvcc 命令行
- GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考
- GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考
- GPU(CUDA)学习日记(八)------ Parallel Nsight2.2调试; CUDA:no source correspandence for breakpoint以及nvcc 命令行
- GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考
- Python文件操作
- Git -- 初学过程
- PAT基础编程题目集--函数集4-(1~5)
- ThinkCMF 和 OneThink内容管理系统对比
- c语言笔试题
- GPU(CUDA)学习日记(三)------ CUDA基本架构介绍以及编程入门!~~
- GPU(CUDA)学习日记(四)----------VS2010 + win7 32位 + CUDA 4.2 环境配置以及一些小问题的解决
- Ubuntu16.04搭建ionic开发环境
- GPU(CUDA)学习日记(五)------ 动态数组一些说明以及Invalid address specified to RtlValidateHeap 错误
- LeetCode--No.217--Contains Duplicate
- GPU(CUDA)学习日记(六)------ vector,动态数组,引用,编程调试经验总结等一些比较琐碎的记录
- HDU 1240 Asteroids! (三维BFS)
- linux下安装过zsh后,使用yum安装autojump后,使用source ./zshrc出现问题
- GPU(CUDA)学习日记(七)------ Parallel Nsight 双机调试经验 以及 一些比较基础的教程