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

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. [CSS3] 学习笔记--CSS盒子模型

    1.CSS盒子模型概述 盒子模型的内容范围包括:margin(外边距).border(边框).padding(内边距).content(内容)部分组成. 2.内边距 内边距在content外,bord ...

  2. [转载] A successful Git branching model/GIT分支管理是一门艺术

    转载自:http://www.cnblogs.com/baiyw/p/3303125.html 英文原文:http://www.nvie.com/posts/a-successful-git-bran ...

  3. JQuery之 serialize() 及serializeArray() 实例介绍

    这两个方法都是jq封装的,主要用于form表单. serialize(); 1.创建一个标准url编码显示的文本字符转: 2.操作的对象是表单元素结合的jq对象: serializeArray(); ...

  4. Activity启动过程分析

    Android的四大组件中除了BroadCastReceiver以外,其他三种组件都必须在AndroidManifest中注册,对于BroadCastReceiver来说,它既可以在AndroidMa ...

  5. 从C#到TypeScript - function

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  6. 【Spring】使用Spring的AbstractRoutingDataSource实现多数据源切换

    最近因为项目需要在做两个项目间数据同步的需求,具体是项目1的数据通过消息队列同步到项目2中,因为这个更新操作还涉及到更新多个库的数据,所以就需要多数据源切换的操作.下面就讲讲在Spring中如何进行数 ...

  7. Java List集合特有方法程序用法

    package Collection; /* Collection |--List:元素是有序的,元素可以重复.因为该集合体系有索引 | |--ArrayList:底层的数据结构使用的是数组结构 特点 ...

  8. 使用jmeter进行APP接口测试经验总结

    声明:我觉得文章不错想保存,如果带来不便请联系我. 使用工具: Fiddler.Jmeter 测试步骤: 1.    确认接口 从开发人员那里获取接口文档,接口文档应该包括完整的功能接口.接口请求方式 ...

  9. shiyandaima

    //jidaxiangronglei #include<iostream> #include<iostream> #include<iomanip> #includ ...

  10. 在SQL Server里如何处理死锁

    在今天的文章里,我想谈下SQL Server里如何处理死锁.当2个查询彼此等待时会发生死锁,没有一个查询可以继续它们的操作.首先我想给你大致讲下SQL Server如何处理死锁.最后我会展示下SQL ...