一、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中表单POST到其他页面的方法

    在ASP中,我们通常把表单提交到另外一个页面(接受数据页面).但是在ASP.NET中,服务端表单通常都是提交到本页面的,如果我设置 form1.action="test.aspx" ...

  2. 【Foreign】减法 [二分][贪心]

    减法 Time Limit: 10 Sec  Memory Limit: 256 MB Description 给你一个n个数的序列A,并且给出m次操作B. 操作的含义是:每次从A中选出不同的B_i个 ...

  3. 【BZOJ】1834 [ZJOI2010]network 网络扩容

    [算法]网络流-最大流+最小费用最大流(费用流) [题解] 第一问跑最大流. 第二问: 原始边相当于费用为0的边,再原图(跑过最大流的图)基础上添加带费用的边,容量为k(相当于inf). 第一问最大流 ...

  4. HDU 5995 Kblack loves flag (模拟)

    题目链接 Problem Description Kblack loves flags, so he has infinite flags in his pocket. One day, Kblack ...

  5. favico.js笔记

    1. favicon.js是什么 一个js库可以使用徽标.图像.视频等来设置网页的favicon,即网页标题栏上的小图标. 2. 如何使用 2.1 使用徽标 basic demo: <!DOCT ...

  6. uboot1.1.6 start.s分析

    .Stage1 start.S代码结构 u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:(1)定义入口.由于一个可执行的Image必须有一个入口点,并 ...

  7. 首次成功的web渗透

    web渗透 今天给大家讲一个最近做的一件令我振奋的一件事情 渗透培训刚刚结束的第二天 我在公网上挖到了我人生中的第一个站 总体来说个人真的很振奋人心      这个网站还没有进行更改但我已经通知了他们 ...

  8. sqlite3_get_table()

    { sqlite3 *db; char *errmsg=NULL;    //用来存储错误信息字符串 char ret=0; int my_age=0;    //类型根据要提取的数据类型而定 cha ...

  9. Spring Cloud Feign 在调用接口类上,配置熔断 fallback后,输出异常

    Spring Cloud Feign 在调用接口类上,配置熔断 fallback后,出现请求异常时,会进入熔断处理,但是不会抛出异常信息. 经过以下配置,可以抛出异常: 将原有ErrorEncoder ...

  10. IDEA 部署项目的时候出错:Jar not loaded错误

    2011-10-18 17:03:52 org.apache.catalina.loader.WebappClassLoader validateJarFile 信息: validateJarFile ...