一、cuda简介

CUDA是支持c++/c语言,一般我喜欢用c来写,他的编译是gpu部分由nvcc来进行的
 
一般的函数定义 void  function();
cuda的函数定义 __global__ void function();
 
解释:在这里,这个global前缀表明这个函数在哪里执行,可以由谁来呼叫
global:主机呼叫,设备执行
host:主机呼叫,主机执行
device:设备呼叫,设备执行
 
执行一般c函数  funtion();
执行cuda函数   function<<>> ();
 
解释:在GPU上面执行函数可以自定分配grid和线程,grid包含线程,因为是并列执行,因此如果内容一样数据的生成很多是不分前后的。
 

二、运行例子的方法:

建立一个CUDA8.0 Runtim模版为基础的工程,
或建立一个c++工程,将cpp后缀改为.cu

建完工程后会有一部分代码

在主函数return 0 之前加入getchar();即可运行,关于此代码后期可慢慢研究,这里不做讲解。

源码为:

#include "cuda_runtime.h"
#include "device_launch_parameters.h" #include <stdio.h> cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size); __global__ void addKernel(int *c, const int *a, const int *b)
{
int i = threadIdx.x;
c[i] = a[i] + b[i];
} int main()
{
const int arraySize = ;
const int a[arraySize] = { , , , , };
const int b[arraySize] = { , , , , };
int c[arraySize] = { }; // Add vectors in parallel.
cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "addWithCuda failed!");
return ;
} printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
c[], c[], c[], c[], c[]); // cudaDeviceReset must be called before exiting in order for profiling and
// tracing tools such as Nsight and Visual Profiler to show complete traces.
cudaStatus = cudaDeviceReset();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaDeviceReset failed!");
return ;
}
getchar();
return ;
} // Helper function for using CUDA to add vectors in parallel.
cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
{
int *dev_a = ;
int *dev_b = ;
int *dev_c = ;
cudaError_t cudaStatus; // Choose which GPU to run on, change this on a multi-GPU system.
cudaStatus = cudaSetDevice();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
goto Error;
} // Allocate GPU buffers for three vectors (two input, one output) .
cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
} cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
} cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
} // Copy input vectors from host memory to GPU buffers.
cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
} cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
} // Launch a kernel on the GPU with one thread for each element.
addKernel<<<, size>>>(dev_c, dev_a, dev_b); // Check for any errors launching the kernel
cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
goto Error;
} // cudaDeviceSynchronize waits for the kernel to finish, and returns
// any errors encountered during the launch.
cudaStatus = cudaDeviceSynchronize();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
goto Error;
} // Copy output vector from GPU buffer to host memory.
cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
} Error:
cudaFree(dev_c);
cudaFree(dev_a);
cudaFree(dev_b); return cudaStatus;
}

三、实战代码:

例一:第一个程序hello world

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <Windows.h>
__global__ void helloFromGPU(void)
{
printf("Hello World from GPU!\n");
} int main(void)
{
// hello from cpu
cudaError_t cudaStatus;
printf("Hello World from CPU!\n"); helloFromGPU << <, >> > ();
cudaDeviceReset();//重置CUDA设备释放程序占用的资源
system("pause");
return ;
}

无视所有错误直接运行即可。

在这里 helloFromGPU << <1, 10 >> >();
表示这一函数将有十个一样的线程,也就是这个函数总计会被执行十次。
 

改为helloFromGPU << <2, 10 >> >();
 

例二:参数的传入

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <Windows.h>
__global__ void Add(int i, int j)
{
int count;
count = i + j;
printf("\nNum is %d\n", count);
}
int main(void)
{
Add << <, >> >(, );
cudaDeviceReset();//重置CUDA设备释放程序占用的资源
system("pause");
return ;
}

传入参数与一般的c没有什么不一样之处

例三:数据的传入和传出

从这里开始要用到显存分配,在这一段中,我们的数据要从内存copy到显存上面,然后现在又要从显存上面copy回来
这次我们定一个减法函数,在设备上执行
__global__ void Decrease(int a, int b, int *c)
{
*c = a - b;
}
我的要传的数为一个整数型的c,一般会定义一个全局的以cuda错误处理返回值为类型的函数,在这一函数内执行数据的传输,及时返回错误
 
cudaError_t  addWithCuda(int *c);
 
在例子中我省略了这个直接用void类型
 
void addWithCuda(int *c);
 
代码:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <Windows.h>
void addWithCuda(int *c);//1.定义传入的函数c
int main(void)
{
int c;
c = ;
addWithCuda(&c);//2.传入参数变量(地址)
cudaDeviceReset();//6.重置CUDA设备释放程序占用的资源
printf("Value is %d", c);//7.主机上打印显示数据 system("pause");
return ;
}
__global__ void Decrease(int a, int b, int *c)
{
*c = a - b;
}
void addWithCuda(int *c)
{
int *dev_c = ;//这个相当于内存和显存有一样的
//3.请求CUDA设备的内存(显存),执行CUDA函数
cudaMalloc((void**)&dev_c, sizeof(int));
Decrease << <, >> >(, , dev_c);
//4.等待设备所有线程任务执行完毕
cudaDeviceSynchronize();
//5.数据复制到主机,释放占用空间
cudaMemcpy(c, dev_c, sizeof(int), cudaMemcpyDeviceToHost);
cudaFree(dev_c);
}

例四:数据的传入和传出Ⅱ

如果要复制数据进去,那么我们先要修改下上一个例子的函数
 
1.传入的数值全改为指针类型
__global__ void Decrease(int *a, int *b, int *c)
{
*c = *a - *b;
}
 
2.修改函数的传入参数
void addWithCuda(int *c,int *a,int *b);//1.定义传入的函数c
 
3.增加处理函数中对于相应存储空间的的申请和释放
void addWithCuda(int *c, int *a, int *b)
{
int *dev_c = ;
int *dev_a = ;
int *dev_b = ;
//3.请求CUDA设备的内存(显存),执行CUDA函数
cudaMalloc((void**)&dev_c, sizeof(int));
cudaMalloc((void**)&dev_a, sizeof(int));
cudaMalloc((void**)&dev_b, sizeof(int)); //4.从主机复制数据到设备上
cudaMemcpy(dev_a, a, sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, sizeof(int), cudaMemcpyHostToDevice); Decrease << < , >> >(dev_a, dev_b, dev_c); //5.等待设备所有线程任务执行完毕
cudaDeviceSynchronize(); //6.数据复制到主机,释放占用空间
cudaMemcpy(c, dev_c, sizeof(int), cudaMemcpyDeviceToHost);
cudaFree(dev_c);
cudaFree(dev_a);
cudaFree(dev_b);
}
 
4.最后是主函数
int main(void)
{
int c;
int a, b;
c = ;
a = ;
b = ;
addWithCuda(&c, &a, &b);//2.传入参数变量(地址)
cudaDeviceReset();//7.重置CUDA设备释放程序占用的资源
printf("Value is %d", c);//8.主机上打印显示数据
system("pause");
return ;
}

5.代码:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <Windows.h>
__global__ void Decrease(int *a, int *b, int *c)
{
*c = *a - *b;
}
void addWithCuda(int *c, int *a, int *b)
{
int *dev_c = ;
int *dev_a = ;
int *dev_b = ;
//3.请求CUDA设备的内存(显存),执行CUDA函数
cudaMalloc((void**)&dev_c, sizeof(int));
cudaMalloc((void**)&dev_a, sizeof(int));
cudaMalloc((void**)&dev_b, sizeof(int)); //4.从主机复制数据到设备上
cudaMemcpy(dev_a, a, sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, sizeof(int), cudaMemcpyHostToDevice); Decrease << < , >> >(dev_a, dev_b, dev_c); //5.等待设备所有线程任务执行完毕
cudaDeviceSynchronize(); //6.数据复制到主机,释放占用空间
cudaMemcpy(c, dev_c, sizeof(int), cudaMemcpyDeviceToHost);
cudaFree(dev_c);
cudaFree(dev_a);
cudaFree(dev_b);
} int main(void)
{
int c;
int a, b;
c = ;
a = ;
b = ;
addWithCuda(&c, &a, &b);//2.传入参数变量(地址)
cudaDeviceReset();//7.重置CUDA设备释放程序占用的资源
printf("Value is %d", c);//8.主机上打印显示数据
system("pause");
return ;
}

最后再放一个程序关于循环可以自行理解

程序实现向量的加法操作,使用了一个block内部的512个线程。

#include <stdio.h>
#include<cuda_runtime.h> //__global__声明的函数,告诉编译器这段代码交由CPU调用,由GPU执行
__global__ void add(const int *dev_a,const int *dev_b,int *dev_c)
{
int i=threadIdx.x;
dev_c[i]=dev_a[i]+dev_b[i];
} int main(void)
{
//申请主机内存,并进行初始化
int host_a[],host_b[],host_c[];
for(int i=;i<;i++)
{
host_a[i]=i;
host_b[i]=i<<;
} //定义cudaError,默认为cudaSuccess(0)
cudaError_t err = cudaSuccess; //申请GPU存储空间
int *dev_a,*dev_b,*dev_c;
err=cudaMalloc((void **)&dev_a, sizeof(int)*);
err=cudaMalloc((void **)&dev_b, sizeof(int)*);
err=cudaMalloc((void **)&dev_c, sizeof(int)*);
if(err!=cudaSuccess)
{
printf("the cudaMalloc on GPU is failed");
return ;
}
printf("SUCCESS");
//将要计算的数据使用cudaMemcpy传送到GPU
cudaMemcpy(dev_a,host_a,sizeof(host_a),cudaMemcpyHostToDevice);
cudaMemcpy(dev_b,host_b,sizeof(host_b),cudaMemcpyHostToDevice); //调用核函数在GPU上执行。数据较少,之使用一个Block,含有512个线程
add<<<,>>>(dev_a,dev_b,dev_c);
cudaMemcpy(&host_c,dev_c,sizeof(host_c),cudaMemcpyDeviceToHost);
for(int i=;i<;i++)
printf("host_a[%d] + host_b[%d] = %d + %d = %d\n",i,i,host_a[i],host_b[i],host_c[i]);
cudaFree(dev_a);//释放GPU内存
cudaFree(dev_b);//释放GPU内存
cudaFree(dev_c);//释放GPU内存
return ;
}

CUDA学习笔记1:第一个CUDA实例的更多相关文章

  1. CUDA学习笔记(三)——CUDA内存

    转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm5f.html 结合lec07_intro_cuda.pptx学习 内存类型 CGMA: Compute ...

  2. CUDA学习笔记(四)——CUDA性能

    转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm5h.html 四.CUDA性能 CUDA中的block被划分成一个个的warp,在GeForce880 ...

  3. CUDA学习笔记(一)——CUDA编程模型

    转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm56.html CUDA的代码分成两部分,一部分在host(CPU)上运行,是普通的C代码:另一部分在d ...

  4. CUDA学习笔记(二)——CUDA线程模型

    转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm5b.html 一个grid中的所有线程执行相同的内核函数,通过坐标进行区分.这些线程有两级的坐标,bl ...

  5. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  6. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  7. Spark学习笔记1——第一个Spark程序:单词数统计

    Spark学习笔记1--第一个Spark程序:单词数统计 笔记摘抄自 [美] Holden Karau 等著的<Spark快速大数据分析> 添加依赖 通过 Maven 添加 Spark-c ...

  8. C#.NET学习笔记2---C#.第一个C#程序

    C#.NET学习笔记2---C#.第一个C#程序 技术qq交流群:JavaDream:251572072  教程下载,在线交流:创梦IT社区:www.credream.com 6.第一个C#程序:   ...

  9. OGG学习笔记02-单向复制配置实例

    OGG学习笔记02-单向复制配置实例 实验环境: 源端:192.168.1.30,Oracle 10.2.0.5 单实例 目标端:192.168.1.31,Oracle 10.2.0.5 单实例 1. ...

  10. Unity3D学习笔记2——绘制一个带纹理的面

    目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...

随机推荐

  1. ASP.NET中防止Access数据库下载

    如何防止Access数据库下载是一个很老的话题了,网上的讨论也比较多.这里我们给出几种在ASP.NET下防止Access数据库被下载的方法. 我们这里假设Access数据库名字为 test.mdb. ...

  2. HDU 1999 不可摸数 (模拟)

    题目链接 Problem Description s(n)是正整数n的真因子之和,即小于n且整除n的因子和.例如s(12)=1+2+3+4+6=16.如果任何数m,s(m)都不等于n,则称n为不可摸数 ...

  3. Python作业工资管理系统(第三周)

    作业内容: 实现效果: 从info.txt文件中读取员工及其工资信息,最后将修改或增加的员工工资信息也写入原info.txt文件. 效果演示: 1. 查询员工工资 2. 修改员工工资 3. 增加新员工 ...

  4. hibernate CasCade deleted object ould be re-saved by cascade

    这个问题个人认为看你用的那种方式,如果是注解式的 比如: @ManyToMany(cascade={CascadeType.MERGE,CascadeType.REFRESH,CascadeType. ...

  5. 【zTree】zTree展开树节点

    今天在做zTree树的时候想着将第一级tree展开,于是利用下面方法: /** * 展开树节点的第一层 */ function openFirstTreenode(){ // 获取树对象 var tr ...

  6. nmon的安装和使用

    1.下载nmon https://zh.osdn.net/projects/sfnet_nmon/downloads/nmon_x86_64_rhel6/ 2../nmon_x86_64_rhel6 ...

  7. git服务器的简单搭建

    安装git 安装git,参考:https://git-scm.com/book/zh/v1/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git 创建git仓库 使用ro ...

  8. Linux下不能挂载NTFS格式硬盘/U盘

    如果大家以后在Ubuntu系统下面遇到NTFS格式的移动硬盘哪个分区不能挂载的话,可以尝试sudo ntfsfix /dev/你相应的分区

  9. ASP.NET Core 2.0 MVC 发布部署--------- IIS 具体操作

    .Net Core 部署到 IIS系统中的步骤 一.IIS 配置 启用 Web 服务器 (IIS) 角色并建立角色服务. 1.Windows Ddesktop 桌面操作系统(win7及更高版本) 导航 ...

  10. HDU 1686 Oulipo(KMP变形求子串出现数目(可重))

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1686 题目大意:给两个字符串A,B求出A中出现了几次B(计算重复部分). 解题思路:稍微对kmp()函 ...