Udacity并行计算课程笔记-The GPU Programming Model
一、传统的提高计算速度的方法
- faster clocks (设置更快的时钟)
- more work over per clock cycle(每个时钟周期做更多的工作)
- more processors(更多处理器)
二、CPU & GPU
- CPU更加侧重执行时间,做到延时小
- GPU则侧重吞吐量,能够执行大量的计算
更形象的理解就是假如我们载一群人去北京,CPU就像那种敞篷跑车一样速度贼快,但是一次只能坐两个人,而GPU就像是大巴车一样,虽然可能速度不如跑车,但是一次能载超多人。
总结起来相比于CPU,GPU有如下特点:
- 有很多计算单元,可以在一起执行大量的计算
- 显示并行计算模型(explicitly parallel programming model),这个会在后面深度讨论
- GPU是对吞吐量进行优化,而不是吞吐量
三、cuda登场
以前我们所写的代码都只能运行在CPU上,那么如果想运行在GPU上该怎么实现呢?
这时候就需要CUDA大大登场了!!!
cuda执行原理是CPU运行主程序,向GPU发送指示告诉它该做什么,那么系统就需要做如下的事情:
- 1.把CPU内存中的数据转移到GPU的内存中
- 2.将数据从GPU移回CPU
(把数据从一个地方移到另一个地方命令为cudaMemcpy) - 3.在GPU上分配内存,在C语言中该命令是malloc,而在cuda中则是cudaMalloc
- 4.在GPU上调用以并行方式计算的程序,这些程序叫做内核。
练习题:GPU可以做如下哪些事?
正确选项解释:
- 选项2:回应CPU发来的请求,即对应上面的步骤2——将数据从GPU移回CPU
- 选项4:回应CPU发来的请求,即对应上面的步骤1——把CPU内存中的数据转移到GPU的内存中
- 选项5:计算由CPU调用的内核运算。
四、A CUDA Program
典型的GPU算法流程:
- CPU在GPU上分配存储空间(cudaMalloc)
- CPU将输入数据拷贝到GPU(cudaMemcpy)
- CPU调用某些内核来监视这些在GPU上处理这个数据的内核(kernel launch)
- CPU将GPU计算得到的结果复制回CPU(cudaMemcpy)
五、定义GPU计算
GPU能做的事是:
- 有效的启动大量线程
- 并行的运行上面启动的大量线程,而不是运行一个有很多并行工作的线程,也不是运行一个线程更加快速。
六、CPU&GPU计算原理区别
下面将计算数组[0,1,2……,63]每个元素平方来比较CPU和GPU计算原理的区别,以及具体代码实现。
CPU
for(i=0;i<64;i++){
out[i] = in[i] * in[i];
}
该段代码在CPU中执行,只有一个线程,它会循环64次,每次迭代做一个计算。
GPU
实现代码:
#include <stdio.h>
__global__ void cube(float * d_out, float * d_in){
// Todo: Fill in this function
int idx = threadIdx.x;
d_out[idx] = d_in[idx]+6;
}
int main(int argc, char ** argv) {
const int ARRAY_SIZE = 64;
const int ARRAY_BYTES = ARRAY_SIZE * sizeof(float);
// generate the input array on the host
float h_in[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
h_in[i] = float(i);
}
float h_out[ARRAY_SIZE];
// declare GPU memory pointers
float * d_in;
float * d_out;
// allocate GPU memory
cudaMalloc((void**) &d_in, ARRAY_BYTES);
cudaMalloc((void**) &d_out, ARRAY_BYTES);
// transfer the array to the GPU
cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);
// launch the kernel
cube<<<1, ARRAY_SIZE>>>(d_out, d_in);
// copy back the result array to the CPU
cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);
// print out the resulting array
for (int i =0; i < ARRAY_SIZE; i++) {
printf("%f", h_out[i]);
printf(((i % 4) != 3) ? "\t" : "\n");
}
cudaFree(d_in);
cudaFree(d_out);
return 0;
}
代码拆解分析:
1.变量命名规则
在编写cuda代码时,需要遵守如下规则,这样可以避免犯不必要的错误。
CPU的变量以h_开头(host),而GPU的变量以d_开头(device)。
2.定义内核函数
__global__ void square(float *d_out, float *d_in){
int idx = threadIdx.x;
float f = d_in[idx];
d_out[idx] = f * f;
}
通过 global 定义的函数可以让cuda知道这是一个内核函数。
函数第一行作用是通过内置的线程索引threadIdx获得当前线程的索引。另外threadIdx是c语言中的struct,它有3名成员,分别是 .x,.y,.z 。如果该线程是第一个线程,则threadIdx.x返回的值是0。
3.数据转移cudaMemcpy
代码片段
// 将数据转移到GPU
cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);
// 调用内核
square<<<1, ARRAY_SIZE>>>(d_out, d_in);
// 将结果传回CPU
cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);
注意下面函数的第三个参数direction有三种选项:
cudaMemcpy(destination, source, size, direction)
分别是:
- cudaMemcpyHostToDevice
- cudaMemcpyDeviceToHost
- cudaMemcpyDeviceToDevice
4.调用内核 square<<<1, 64>>>
另外在解释一下如上函数各参数的含义:
第一个参数1表示需要分配的块的数量为1,
第二个参数64表示每一块有64个线程。
所以假设我们需要1280个线程,我们就可以这样定义:
square<<<10,128>>>(param1, param2);
或者
square<<<5,256>>>(param1, param2);
BUT!!! 要注意不能像下面这样定义,因为一个块的线程数一般没那么大,一般只有1024.
square<<<1,1280>>>(param1, param2);
还需要知道的是上面介绍的两个参数其实可以是二维或者三维的,即
square<<<1,64>>> 等效为 square<<<dim3(1,1,1),dim3(64,1,1)>>> ,但是dim3(64,1,1)=dim3(64)=64。
例如我们有一个128*128的图片,现在需要对每一个像素进行计算,我们可以是
<<<dim3(128,1,1),(128,1,1)>>>,也可以是<<<dim3(8,8,1),dim3(16,16,1)>>>
总结起来核函数的调用的完整形式是
kernel<<<dim3(bx,by,bz), dim3(tx,ty,tz), shmem>>>(...)
第一个参数表示网络块的维数(bx * by * bz),
第二个参数表示每块所含有的线程数(tx * ty * tz)
第三个参数一般默认为0,它是以字节表示的每个线程块分配的共享内存量
![]https://ask.qcloudimg.com/http-save/yehe-1215004/q3rf2iq5r.png?imageView2/2/w/1620)
Udacity并行计算课程笔记-The GPU Programming Model的更多相关文章
- Udacity并行计算课程笔记-The GPU Hardware and Parallel Communication Patterns
本小节笔记大纲: 1.Communication patterns gather,scatter,stencil,transpose 2.GPU hardware & Programming ...
- 【Udacity并行计算课程笔记】- lesson 1 The GPU Programming Model
一.传统的提高计算速度的方法 faster clocks (设置更快的时钟) more work over per clock cycle(每个时钟周期做更多的工作) more processors( ...
- 【Udacity并行计算课程笔记】- Lesson 2 The GPU Hardware and Parallel Communication Patterns
本小节笔记大纲: 1.Communication patterns gather,scatter,stencil,transpose 2.GPU hardware & Programming ...
- 【Udacity并行计算课程笔记】- Lesson 4 Fundamental GPU Algorithms (Applications of Sort and Scan)
I. Scan应用--Compact 在介绍这节之前,首先给定一个情景方便理解,就是因为某种原因我们需要从扑克牌中选出方块的牌. 更formal一点的说法如下,输入是 \(s_0,s_1,...\), ...
- 【Udacity并行计算课程笔记】- Lesson 3 Fundamental GPU Algorithms (Reduce, Scan, Histogram)
本周主要内容如下: 如何分析GPU算法的速度和效率 3个新的基本算法:归约.扫描和直方图(Reduce.Scan.Histogram) 一.评估标准 首先介绍用于评估GPU计算的两个标准: ste ...
- Udacity并行计算课程 CS344 编程作业答案
Problem set 1 // Homework 1 // Color to Greyscale Conversion //A common way to represent color image ...
- 深度学习课程笔记(十七)Meta-learning (Model Agnostic Meta Learning)
深度学习课程笔记(十七)Meta-learning (Model Agnostic Meta Learning) 2018-08-09 12:21:33 The video tutorial can ...
- 深度学习课程笔记(二)Classification: Probility Generative Model
深度学习课程笔记(二)Classification: Probility Generative Model 2017.10.05 相关材料来自:http://speech.ee.ntu.edu.tw ...
- 把书《CUDA By Example an Introduction to General Purpose GPU Programming》读薄
鉴于自己的毕设需要使用GPU CUDA这项技术,想找一本入门的教材,选择了Jason Sanders等所著的书<CUDA By Example an Introduction to Genera ...
随机推荐
- TFboy养成记 MNIST Classification (主要是如何计算accuracy)
参考:莫烦. 主要是运用的MLP.另外这里用到的是批训练: 这个代码很简单,跟上次的基本没有什么区别. 这里的lossfunction用到的是是交叉熵cross_entropy.可能网上很多形式跟这里 ...
- openstack pike 使用 linuxbridge + vxlan
#openstack pike 使用 linuxbridge + vxlan #openstack pike 集群高可用 安装部署 汇总 http://www.cnblogs.com/elvi/p/ ...
- 企业实战Nginx+Tomcat动静分离架构的技术分享
Nginx动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离.严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat.Re ...
- LINQ学习系列-----3.1 查询非泛型集合
一.问题起源 LINQ to object在设计时,是配合IEnumerable<T>接口的泛型集合类型使用的,例如字典.数组.List<T>等,但是对于继承了IEnumera ...
- 常量和静态变量会先载入内存后在进行执行php代码
static $test=1;//在php执行前就已经写入内存$test++;var_dump($test);static $test=10;//在php执行前就已经写入内存var_dump($tes ...
- 删除kafka的topic及kafka基本命令
kafka的topic默认是不允许被删除的,删除后在topic后会出现”marked for deletion”字样,实际并未删除,现在创建同样的topic会提示topic已经存在. 解决办法: se ...
- 《跟我学IDEA》一、下载安装idea,设置背景字体编码,配置JDK
写在前面的话:作为一个在IT界摸爬滚打6年+的老程序员,我属于会的东西多而杂,但是没有任何一样精通的.曾经自己也认真过,蹉跎过,最近和别的同事朋友聊天时,突然发现自己得到的东西却很少很少,于是想认真的 ...
- Solr6.5.0配置中文分词器配置
准备工作: solr6.5.0安装成功 1.去官网https://github.com/wks/ik-analyzer下载IK分词器 2.Solr集成IK a)将ik-analyzer-solr6.x ...
- DDD峰会归来话DDD
一场大戏落幕,首届DDD中国峰会如大会主题色一般的红.或许在12月9日这一天,全中国的DDD粉丝大约有一半都汇聚在了国家会议中心.听起来是幸,其实是不幸,因为DDD在中国的人群基数实在是太少了. 因为 ...
- Python爬虫(十七)_糗事百科案例
糗事百科实例 爬取糗事百科段子,假设页面的URL是: http://www.qiushibaike.com/8hr/page/1 要求: 使用requests获取页面信息,用XPath/re做数据提取 ...