cuda实现向量相加

博客最后附上整体代码

如果有说的不对的地方还请前辈指出, 因为cuda真的接触没几天

一些总结(建议看)

  1. cuda 并不纯GPU在运行程序, 而是 cpu 与 gpu 一起在运行程序, cpu负责调度, gpu 负责运算, cpu称为**HOST **, gpu 称为 DEVICE
  2. 记住三个东西 grid block thread ,关系分别是 grid 包含多个 block , block 包含多个 thread
  3. 一个block中thread个数选取一般为32的整数倍, 原因和warp有关, 有兴趣自行查阅
  4. 一个grid中block的个数选取和你的kernel函数以及thread数量有关, 举个例子, int a[1000] 加上 int b[1000] , 你的thread为64, 那么, block = 1000/64 = 16个合适
  5. __global__函数一般表示一个内核函数,是一组由GPU执行的并行计算任务,由cpu调用
  6. __host__一般是由CPU调用,由CPU执行的函数,
  7. __device__一般表示由GPU中一个线程调用的函数

代码实现

引入

#include <stdio.h>
#include <cuda_runtime.h>

kernel函数

__global__ void
vectorAdd(float *a, float *b, float *c, int num){
int i = blockDim.x * blockIdx.x + threadIdx.x; //vector is 1-dim, blockDim means the number of thread in a block
if(i < num){
c[i] = a[i] + b[i];
}
}

int i = blockDim.x * blockIdx.x + threadIdx.x;

这句代码解释一下:

blockDim.x 表示block的size行数(如果是一维的block的话,即一行有多少个thread)

blockIdx.x 表示当前运行到的第几个block(一维grid的话,即该grid中第几个block)

threadIdx.x 表示当前运行到的第几个thread (一维的block的话.即该block中第几个thread)

画个图解释一下

比如上面这个图的话, ABCDE各代表一个block, 总的为一个Grid, 每个block中有四个thread, 图中我花了箭头的也就是代表着第1个block中的第0个thread.

那么 i = blockDim.x * blockIdx.x + threadIdx.x 就是指 i = 4 * 1 + 0

申请内存空间与释放

host中申请内存

float *a = (float *)malloc(size);
float *b = (float *)malloc(size);
float *c = (float *)malloc(size); free(a);
free(b);
free(c);

device中申请内存

float *da = NULL;
float *db = NULL;
float *dc = NULL; cudaMalloc((void **)&da, size);
cudaMalloc((void **)&db, size);
cudaMalloc((void **)&dc, size); cudaFree(da);
cudaFree(db);
cudaFree(dc);

host中内存copy到device

cudaMemcpy(da,a,size,cudaMemcpyHostToDevice);
cudaMemcpy(db,b,size,cudaMemcpyHostToDevice);
cudaMemcpy(dc,c,size,cudaMemcpyHostToDevice);

上面的cudaMemcpyHostToDevice用于指定方向有四种关键词

cudaMemcpyHostToDevice | cudaMemcpyHostToHost | cudaMemcpyDeviceToDevice | cudaMemcpyDeviceToHost

启动 kernel函数

int threadPerBlock = 256;
int blockPerGrid = (num + threadPerBlock - 1)/threadPerBlock;
vectorAdd <<< blockPerGrid, threadPerBlock >>> (da,db,dc,num)

此处确定了block中的thread数量以及一个grid中block数量

利用kernel function <<< blockPerGrid, threadPerBlock>>> (paras,...) 来实现在cuda中运算

参考

https://zhuanlan.zhihu.com/p/345877391

https://docs.nvidia.com/cuda/cuda-c-programming-guide/

源码展示

#include <stdio.h>

#include <cuda_runtime.h>

// vectorAdd run in device
__global__ void
vectorAdd(float *a, float *b, float *c, int num){
int i = blockDim.x * blockIdx.x + threadIdx.x; //vector is 1-dim, blockDim means the number of thread in a block
if(i < num){
c[i] = a[i] + b[i];
}
} // main run in host
int
main(void){
int num = 10000; // size of vector
size_t size = num * sizeof(float); // host memery
float *a = (float *)malloc(size);
float *b = (float *)malloc(size);
float *c = (float *)malloc(size); // init the vector
for(int i=1;i<num;++i){
a[i] = rand()/(float)RAND_MAX;
b[i] = rand()/(float)RAND_MAX;
} // copy the host memery to device memery
float *da = NULL;
float *db = NULL;
float *dc = NULL; cudaMalloc((void **)&da, size);
cudaMalloc((void **)&db, size);
cudaMalloc((void **)&dc, size); cudaMemcpy(da,a,size,cudaMemcpyHostToDevice);
cudaMemcpy(db,b,size,cudaMemcpyHostToDevice);
cudaMemcpy(dc,c,size,cudaMemcpyHostToDevice); // launch function add kernel
int threadPerBlock = 256;
int blockPerGrid = (num + threadPerBlock - 1)/threadPerBlock;
printf("threadPerBlock: %d \nblockPerGrid: %d \n",threadPerBlock,blockPerGrid); vectorAdd <<< blockPerGrid, threadPerBlock >>> (da,db,dc,num); //copy the device result to host
cudaMemcpy(c,dc,size,cudaMemcpyDeviceToHost); // Verify that the result vector is correct
for (int i = 0; i < num; ++i){
if (fabs(a[i] + b[i] - c[i]) > 1e-5){
fprintf(stderr, "Result verification failed at element %d!\n", i);
return 0;
}
} printf("Test PASSED\n"); // Free device global memory
cudaFree(da);
cudaFree(db);
cudaFree(dc);
// Free host memory
free(a);
free(b);
free(c); printf("free is ok\n");
return 0;
}

cuda实现向量相加的更多相关文章

  1. 向量相加CUDA练习

    #include<string.h> #include<math.h> #include<stdlib.h> #include<stdio.h> #de ...

  2. tensorflow中一个矩阵和一个向量相加

    import tensorflow as tf x=tf.constant([[1,2],[3,4]]) y=tf.constant([[1],[1]])#列向量 z=tf.constant([1,1 ...

  3. CUDA从入门到精通

    http://blog.csdn.net/augusdi/article/details/12833235 CUDA从入门到精通(零):写在前面 在老板的要求下.本博主从2012年上高性能计算课程開始 ...

  4. cuda编程学习3——VectorSum

    这个程序是把两个向量相加 add<<<N,1>>>(dev_a,dev_b,dev_c);//<N,1>,第一个参数N代表block的数量,第二个参数1 ...

  5. cuda学习1-初始庐山真面目

    cuda作为gpu计算中的代表,拥有着超级高的计算效率,其原因是gpu实际相当与一台超级并行机组,使用过MPI做并行计算的人们可能知道,所谓的并行计算,简单讲就是用多个U(计算单元)来完成一个U的计算 ...

  6. cuda学习2-block与thread数量的选取

    由上一节可知,在main函数中,cuda程序的并行能力是在add<<<N,1>>>( dev_a, dev_b, dev_c )函数中体现的,这里面设置的是由N个b ...

  7. CUDA从入门到精通 - Augusdi的专栏 - 博客频道 - CSDN.NET

    http://blog.csdn.net/augusdi/article/details/12833235 CUDA从入门到精通 - Augusdi的专栏 - 博客频道 - CSDN.NET CUDA ...

  8. CUDA Samples: Long Vector Add

    以下CUDA sample是分别用C++和CUDA实现的两个非常大的向量相加操作,并对其中使用到的CUDA函数进行了解说,各个文件内容如下: common.hpp: #ifndef FBC_CUDA_ ...

  9. CUDA Samples:Vector Add

    以下CUDA sample是分别用C++和CUDA实现的两向量相加操作,参考CUDA 8.0中的sample:C:\ProgramData\NVIDIA Corporation\CUDA Sample ...

随机推荐

  1. 【python基础】使用import导入相对路径的源文件

    前言 在编写python代码的过程中,不同路径下的源码文件该如何引用,这是个问题,本文针对这个问题介绍解决方法. 源码目录结构: . ├── conf.py ├── main.py ├── mod/ ...

  2. Java基础教程:枚举类型

    Java基础教程:枚举类型 枚举类型 枚举是将一具有类似特性的值归纳在一起的方法.比如,我们可以将周一到周日设计为一个枚举类型.彩虹的七种颜色设计为一个枚举类型. 常量实现枚举 我们通过定义常量的方式 ...

  3. [MySQL]MySQL数据库中如何查询分组后每组中的最后一条记录?

    原文地址:https://codedefault.com/s/how-can-i-retrieve-the-last-record-in-each-group-mysql 问题描述 比如,在MySQL ...

  4. nnexus3 破解密码

    主要步骤如下: 1.停服 2.进入OrientDB控制台:java -jar /usr/local/nexus/lib/support/nexus-orient-console.jar 3.在控制台执 ...

  5. 2019.12.12 Java的多线程&匿名类

    Java基础(深入了解概念为主) 匿名类 定义 Java匿名类很像局部或内联系,只是没有明细.我们可以利用匿名类,同时定义并实例化一个类.只有局部类仅被使用一次时才应该这么做. 匿名类不能有显式定义的 ...

  6. LeetCode 141. 环形链表(Linked List Cycle) 19

    141. 环形链表 141. Linked List Cycle 题目描述 给定一个链表,判断链表中是否有环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 ...

  7. (7)Spring Boot web开发 --- servlet容器

    文章目录 配置嵌入式 Servlet 容器 注册 三大组件 使用其他 servlet 容器 使用外置的 `Servlet` 容器 配置嵌入式 Servlet 容器 Spirng Boot 默认使用自带 ...

  8. CMakeLists 添加 -pthread 编译选项 undefined reference to pthread_atfork

    在与 main() 函数同级的 CMakeLists 中添加如下内容(根据项目实际情况修改): cmake_minimum_required (VERSION 2.6) find_package (T ...

  9. PAT(B) 1068 万绿丛中一点红(C)

    题目链接:1068 万绿丛中一点红 (20 point(s)) 参考博客:1068. 万绿丛中一点红(20) i逆天耗子丶 题目描述 对于计算机而言,颜色不过是像素点对应的一个 24 位的数值.现给定 ...

  10. AX 2009中现有量画面修改

    前端时间开发一个东西,需要在现有量画面增加一个字段 但是发现这个display方法写在任何数据源下面都不行,数据取的不对. 因为InventSum这个表只有所有维度都出来时才会有对应关联的invent ...