CUDA学习:第一CUDA代码:数组求和

今天有些收获了,成功运行了数组求和代码:就是将N个数相加求和

//环境:CUDA5.0,vs2010

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

cudaError_t addWithCuda(int *c, int *a);

#define TOTALN 72120
#define BLOCKS_PerGrid 32
#define THREADS_PerBlock 64 //2^8

__global__ void SumArray(int *c, int *a)//, int *b)
{
__shared__ unsigned int mycache[THREADS_PerBlock];//设置每个块内同享内存threadsPerBlock==blockDim.x

int i = threadIdx.x+blockIdx.x*blockDim.x;
int j = gridDim.x*blockDim.x;//每个grid里一共有多少个线程
int cacheN;
unsigned sum,k;

sum=0;

cacheN=threadIdx.x; //

while(i<TOTALN)
{
sum += a[i];// + b[i];
i = i+j;
}

mycache[cacheN]=sum;

__syncthreads();//对线程块进行同步;等待该块里所有线程都计算结束

//下面开始计算本block中每个线程得到的sum(保存在mycache)的和
//递归方法:(参考《GPU高性能编程CUDA实战中文》)
//1:线程对半加:

k=THREADS_PerBlock>>1;
while(k)
{
if(cacheN<k)
{
//线程号小于一半的线程继续运行这里加
mycache[cacheN] += mycache[cacheN+k];//数组序列对半加,得到结果,放到前半部分数组,为下次递归准备
}
__syncthreads();//对线程块进行同步;等待该块里所有线程都计算结束
k=k>>1;//数组序列,继续对半,准备后面的递归
}

//最后一次递归是在该块的线程0中进行,所有把线程0里的结果返回给CPU
if(cacheN==0)
{
c[blockIdx.x]=mycache[0];
}

}

int main()
{

int a[TOTALN] ;
int c[BLOCKS_PerGrid] ;

unsigned int j;
for(j=0;j<TOTALN;j++)
{
//初始化数组,您可以自己填写数据,我这里用1
a[j]=1;
}

// 进行并行求和
cudaError_t cudaStatus = addWithCuda(c, a);

if (cudaStatus != cudaSuccess) {
fprintf(stderr, "addWithCuda failed!");
return 1;
}

unsigned int sum1,sum2;
sum1=0;
for(j=0;j<BLOCKS_PerGrid;j++)
{
sum1 +=c[j];
}
//用CPU验证和是否正确

sum2=0;
for(j=0;j<TOTALN;j++)
{
sum2 += a[j];
}

printf("sum1=%d; sum2=%d\n",sum1,sum2);

// 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 1;
}

return 0;
}

// Helper function for using CUDA to add vectors in parallel.

cudaError_t addWithCuda(int *c, int *a)
{
int *dev_a = 0;
int *dev_b = 0;
int *dev_c = 0;
cudaError_t cudaStatus;

// Choose which GPU to run on, change this on a multi-GPU system.
cudaStatus = cudaSetDevice(0);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
goto Error;
}

// 申请一个GPU内存空间,长度和main函数中c数组一样
cudaStatus = cudaMalloc((void**)&dev_c, BLOCKS_PerGrid * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
}
// 申请一个GPU内存空间,长度和main函数中a数组一样
cudaStatus = cudaMalloc((void**)&dev_a, TOTALN * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Copy input vectors from host memory to GPU buffers.
//将a的数据从cpu中复制到GPU中
cudaStatus = cudaMemcpy(dev_a, a, TOTALN * sizeof(int), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////

// Launch a kernel on the GPU with one thread for each element.
//启动GPU上的每个单元的线程
SumArray<<<BLOCKS_PerGrid, THREADS_PerBlock>>>(dev_c, dev_a);//, dev_b);

// 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, BLOCKS_PerGrid * sizeof(int), cudaMemcpyDeviceToHost);
//cudaStatus = cudaMemcpy(b, dev_b, size * sizeof(int), cudaMemcpyDeviceToHost);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
}

Error:
cudaFree(dev_c);
cudaFree(dev_a);

return cudaStatus;
}

时间: 2024-09-29 22:42:07

CUDA学习:第一CUDA代码:数组求和的相关文章

Swift学习第一天之数组

Swift学习第一天: 1:数组的使用 数组的定义: let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 2:数组的遍历 for num in numbers { print(num) } 3:也是通过下标来制定内容 let num1 = numbers[0] let num2 = numbers[1] 4.定义可变不可变 `let` 定义不可变数组 `var` 定义可变数组 5.向可变数组里面追加内容 array1.append("wangwu"

CUDA学习,第一个kernel函数及代码讲解

前一篇CUDA学习,我们已经完成了编程环境的配置,现在我们继续深入去了解CUDA编程.本博文分为三个部分,第一部分给出一个代码示例,第二部分对代码进行讲解,第三部分根据这个例子介绍如何部署和发起一个kernel函数. 一.代码示例 二.代码解说 申明一个函数,用于检测CUDA运行中是否出错. kernel函数,blockIdx.x表示block在x方向的索引号,blockDim.x表示block在x方向的维度,threadIdx.x表示thread在x方向的索引号. 这里也许你会问,为什么在x方

cuda学习3-共享内存和同步

为什么要使用共享内存呢,因为共享内存的访问速度快.这是首先要明确的,下面详细研究. cuda程序中的内存使用分为主机内存(host memory) 和 设备内存(device memory),我们在这里关注的是设备内存.设备内存都位于gpu之上,前面我们看到在计算开始之前,每次我们都要在device上申请内存空间,然后把host上的数据传入device内存.cudaMalloc()申请的内存,还有在核函数中用正常方法申请的变量的内存.这些内存叫做全局内存,那么还有没有别的内存种类呢?常用的还有共

CUDA学习笔记(二)【转】

来源:http://luofl1992.is-programmer.com/posts/38847.html 编程语言的特点是要实践,实践多了才有经验.很多东西书本上讲得不慎清楚,不妨自己用代码实现一下. 作为例子,我参考了书本上的矩阵相乘的例子,这样开始写代码,然后很自然地出现了各种问题. 以下的内容供大家学习参考,有问题可以留言与我反馈. 开始学着使用 CUDA,实现一个矩阵乘法运算. 首先我们要定义一个矩阵的结构体,话说CUDA是否支持结构体作为设备端的函数的参数呢? 不妨都一股脑试验一下

CUDA学习之二:shared_memory使用,矩阵相乘

CUDA中使用shared_memory可以加速运算,在矩阵乘法中是一个体现. 矩阵C = A * B,正常运算时我们运用 C[i,j] = A[i,:] * B[:,j] 可以计算出结果.但是在CPU上完成这个运算我们需要大量的时间,设A[m,n],B[n,k],那么C矩阵为m*k,总体,我们需要做m*n*k次乘法运算,m*(b-1)*k次加法运算,并且是串行执行,总体的复杂度为O(m*n*k) . 矩阵类: 1 class Matrix 2 { 3 public: 4 int cols; /

CUDA学习之一:二维矩阵加法

今天忙活了3个小时,竟然被一个苦恼的CUDA小例程给困住了,本来是参照Rachal zhang大神的CUDA学习笔记来一个模仿,结果却自己给自己糊里糊涂,最后还是弄明白了一些. RZ大神对CUDA关于kernel,memory的介绍还是蛮清楚,看完决定写一个二维数组的加法.如果是C++里的加法,那就简单了,用C[i][j] = A[i][j] +B[i][j]就可以. 1 void CppMatAdd(int A[M][N],int B[M][N],int C[M][N]){ 2 for(int

CUDA学习5 常量内存与事件

当线程束中的所有线程都访问相同的只读数据时,使用常量内存将获得额外的性能提升. 常量内存大小限制为64k. 以下摘自hackairM的博文CUDA学习--内存处理之常量内存(4). 常量内存其实只是全局内存的一种虚拟地址形式,并没有特殊保留的常量内存块.常量内存有两个特性,一个是高速缓存,另一个是它支持将单个值广播到线程束中的每个线程.但要注意的是,对于那些数据不太集中或者数据重用率不高的内存访问,尽量不要使用常量内存. 当常量内存将数据分配或广播到线程束中的每个线程时(注意,实际上硬件会将单次

《GPU高性能编程CUDA实战》中代码整理

CUDA架构专门为GPU计算设计了一种全新的模块,目的是减轻早期GPU计算中存在的一些限制,而正是这些限制使得之前的GPU在通用计算中没有得到广泛的应用. 使用CUDA C来编写代码的前提条件包括:(1).支持CUDA的图形处理器,即由NVIDIA推出的GPU显卡,要求显存超过256MB:(2).NVIDIA设备驱动程序,用于实现应用程序与支持CUDA的硬件之间的通信,确保安装最新的驱动程序,注意选择与开发环境相符的图形卡和操作系统:(3).CUDA开发工具箱即CUDA Toolkit,此工具箱

CUDA学习之从CPU架构说起

最近要学习GPU编程,就去英伟达官网下载CUDA, 遇到的第一个问题就是架构的选择 所以我学习的CUDA的第一步是从学习认识CPU架构开始的,x86-64简称x64,是64位版的x86指令集,向前兼容与16位版和32位版的x86架构.x64最初是由AMD于1999年设计完成,AMD首次公开64位集以扩充给x86,称为“AMD64”.后来也被Intel所采用,又被intel 叫做“Intel 64”. 那么ppc64le又指什么呢,下面引用wiki上的两段话“ ppc64 是Linux和GCC开源