这个程序是把两个向量相加

add<<<N,1>>>(dev_a,dev_b,dev_c);//<N,1>,第一个参数N代表block的数量,第二个参数1代表每个block中thread的数量

tid=blockIdx.x;//blockIdx是一个内置变量,blockIdx.x代表这是一个2维索引

下面对这个程序做几个变化,并指出相应的程序应该改变的地方:

1.若启动1个block,每个block中有N个线程。改变:

add<<<1,N>>>(dev_a,dev_b,dev_c);

tid=threadIdx.x

2.此程序N的大小为10,N是向量的大小,若N更大呢?硬件对线程块的数量是有限制的,对每个线程块中线程的数量也是有限制的,可以通过运行deviceQuery进行查看,我是NVIDIA Geforce 750Ti,cuda7.5,线程块数量不能超过65535,每个线程块中线程的数量不能超过1024。若所求的向量中元素大于最多能启动的线程块数量和每个线程块中最大线程数量呢?改变:

add<<<m,n>>>(dev_a,dev_b,dev_c)//m为启动的block数量,n为每个block中thread数量

tid=threadIdx.x+blockIdx.x*blockDim.x;//blockDim是一个内置变量,保存的是线程块中每一维的线程的数量

注意:m应该=N/n,但是若n不能整除N呢?答案:m=(N+n-1)/n,即为大于或等于N的n的最小倍数

3.若向量大小N大于总的可启动线程数量(最大block数量×block中最大thread数量)呢?改变:

add<<<128,1024>>>(dev_a,dev_b,dev_c);

tid=threadIdx.x+blockIdx.x*blockDim.x;

while(tid<N)

{
c[tid]=a[tid]+b[tid];

tid+=blockDim.x*gridDim.x;
}

注意:此处启动了128个block,每个block有1024个thread,用户可以更改这个值,此处只是以<128,1024>为例。

tid+=blockDim.x*gridDim.x;一次循环,执行的线程数量为blockDim.x*gridDim.x,即线程块大小×线程块数量。

代码:

/*
============================================================================
Name : VectorSum-CUDA.cu
Author : can
Version :
Copyright : Your copyright notice
Description : CUDA compute reciprocals
============================================================================
*/
#include<iostream>
using namespace std;
#define N 10
__global__ void add(int *a,int *b,int *c);
static void checkCudaErrorAux(const char *,unsigned, const char *,cudaError_t);
#define CUDA_CHECK_RETURN(value) checkCudaErrorAux(__FILE__,__LINE__,#value,value)
int main()
{
int a[N],b[N],c[N];
int *dev_a,*dev_b,*dev_c;
for(int i=0;i<N;i++)
{
a[i]=i;
b[i]=i*i;
}
CUDA_CHECK_RETURN(cudaMalloc((void **)&dev_a,N*sizeof(int)));
CUDA_CHECK_RETURN(cudaMalloc((void **)&dev_b,N*sizeof(int)));
CUDA_CHECK_RETURN(cudaMalloc((void **)&dev_c,N*sizeof(int)));
CUDA_CHECK_RETURN(cudaMemcpy(dev_a,a,N*sizeof(int),cudaMemcpyHostToDevice));
CUDA_CHECK_RETURN(cudaMemcpy(dev_b,b,N*sizeof(int),cudaMemcpyHostToDevice));
add<<<N,1>>>(dev_a,dev_b,dev_c);//<N,1>,第一个参数N代表block的数量,第二个参数1代表每个block中thread的数量
CUDA_CHECK_RETURN(cudaMemcpy(c,dev_c,N*sizeof(int),cudaMemcpyDeviceToHost));
for(int j=0;j<N;j++)
{
cout<<a[j]<<" + "<<b[j]<<" = "<<c[j]<<endl;
}
return 0;
}

__global__ void add(int* a,int* b,int* c)
{
int tid=blockIdx.x;//blockIdx是一个内置变量,blockIdx.x代表这是一个2维索引
if(tid<N)//避免出错造成非法内存访问
{
c[tid]=a[tid]+b[tid];
}
}

static void checkCudaErrorAux(const char *file,unsigned line, const char *statement,cudaError_t error)
{
if(error==cudaSuccess)
{
return;
}
cout<<statement<<"returned:"<<cudaGetErrorString(error)<<" at file:"<<file<<" line:"<<line<<endl;
exit(1);
}

cuda编程学习3——VectorSum的更多相关文章

  1. CUDA编程学习笔记1

    CUDA编程模型是一个异构模型,需要CPU和GPU协同工作. host和device host和device是两个重要的概念 host指代CPU及其内存 device指代GPU及其内存 __globa ...

  2. CUDA编程学习相关

    1. CUDA编程之快速入门:https://www.cnblogs.com/skyfsm/p/9673960.html 2. CUDA编程入门极简教程:https://blog.csdn.net/x ...

  3. CUDA编程学习(一)

    /****c code****/ #include<stdio.h> int main() { printf("Hello world!\n); ; } /****CUDA co ...

  4. cuda编程学习6——点积dot

    __shared__ float cache[threadPerBlock];//声明共享内存缓冲区,__shared__ __syncthreads();//对线程块中的线程进行同步,只有都完成前面 ...

  5. cuda编程学习5——波纹ripple

    /共有DIM×DIM个像素,每个像素对应一个线程dim3 blocks(DIM/16,DIM/16);//2维dim3 threads(16,16);//2维kernel<<<blo ...

  6. cuda编程学习4——Julia

    书上的例子编译会有错误,修改一下行即可. __device__ cuComplex(float a,float b):r(a),i(b){} /* ========================== ...

  7. cuda编程学习2——add

    cudaMalloc()分配的指针有使用限制,设备指针的使用限制总结如下: 1.可以将其传递给在设备上执行的函数 2.可以在设备代码中使用其进行内存的读写操作 3.可以将其传递给在主机上执行的函数 4 ...

  8. cuda编程学习1——hello world!

    将c程序最简单的hello world用cuda编写在GPU上执行,以下为代码: #include<iostream>using namespace std;__global__ void ...

  9. CUDA编程学习笔记2

    第二章 cuda代码写在.cu/.cuh里面 cuda 7.0 / 9.0开始,NVCC就支持c++11 / 14里面绝大部分的语言特性了. Dim3 __host__ __device__ dim3 ...

随机推荐

  1. C++编程练习(6)----“实现简单的队列的链式存储结构“

    队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出.简称链队列. 实现代码如下: /* LinkQueue.h 头文件 */ #include<iostream> #defi ...

  2. seq语句随笔

    1.UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果. 2.UNION ALL只是简单的将两个结果合并后就返回.这样,如果返回的两个结 ...

  3. Ninject之旅之十二:Ninject在Windows Form程序上的应用(附程序下载)

    摘要: 下面的几篇文章介绍如何使用Ninject创建不同类型的应用系统.包括: Windows Form应用系统 ASP.NET MVC应用系统 ASP.NET Web Form应用系统 尽管对于不同 ...

  4. iOS Plist 文件的 增 删 改

    一:Plist 文件的创建 Plist 文件作为我们IOS开发的一种数据存储文件,还是经常会用到的.在看<X-code江湖录>的时候,看到了这一点.自己就写了一下,把写的东西分享出来!先看 ...

  5. 中国大学MOOC中的后台文件传输

    早期版本的中国大学MOOC一旦被挂起后,应用在完成当前下载任务后无法继续添加新任务,当然也无法将缓存状态写入数据库.这个问题能否顺利解决直接关系到用户体验. 顺便吐槽下,凡是使用了后台文件传输还提示你 ...

  6. C#委托简介

    C#中委托是一种引用类型,该引用类型与其他引用类型不同,在委托对象的引用中存放的不是对数据的引用而是存放对方法的引用,即委托的内部包含一个指向某个方法的指针.通过使用委托把方法的引用封装在委托对象中, ...

  7. 浅谈-Lambda

    Lambda简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能之一. 简介: lambda运算符:所有的lambda表达式都是用新的lambda运算符 &qu ...

  8. JAVA中的数据结构 - 真正的去理解红黑树

    一, 红黑树所处数据结构的位置: 在JDK源码中, 有treeMap和JDK8的HashMap都用到了红黑树去存储 红黑树可以看成B树的一种: 从二叉树看,红黑树是一颗相对平衡的二叉树 二叉树--&g ...

  9. 初学jQuery之jQuery选择器

    今天我们就谈论一下jquery选择器,它们大致分成了四种选择器!!!! 1.基本选择器(标签,ID,类,并集,交集,全局) 1.0(模板) <body> <div id=" ...

  10. CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”

    在GOPaint的设计研究过程中,我一直希望能够实现这样的结果(A B C 3个步骤) 在我之前的博客里面,曾经有过缩略图显示的现就(http://www.cnblogs.com/jsxyhelu/p ...