64
NVIDIA CUDA 件和 GPU 并行算架构 David B. Kirk, Chief Scientist

NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

NVIDIA CUDA 软件和 GPU 并行计算架构

David B. Kirk, Chief Scientist

Page 2: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

2

提纲

GPU 计算的应用

CUDA 编程模型介绍

用CUDA 编程 – 基础

如何开始!

练习 / 实例家庭作业

Page 3: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

3

未来科学和工程突破的关键在于计算

计算

建模

计算

化学

计算

医学

计算

物理学

计算

生物学

计算

金融

计算

地球科学

计算

图像处理

Page 4: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

4

快不仅仅是 “快”

2-3X 快只是“快”

做多一些, 等待少一些

不会改变你如何工作

5-10x 快是 “重大的”

值得升级

值得重写应用软件(部分)

100x+ 快是 “根本不同”

值得考虑新的平台

值得重新构架应用软件

使新的应用软件成为可能

驱动 “time to discovery” 并且在科学中创造基本的变化

Page 5: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

5

GPU 是一个新的计算引擎

相对浮点性能

Eraof Shaders

Fully Programmable

0

10

20

30

40

50

60

70

80

2002 2003 2004 2005 2006

G80

1

Page 6: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

6

CPU-GPU 紧密耦合

Operation 1 Operation 2 Operation 3

Init

Alloc

Function Lib Lib Function Function

CPU

GPU

集成的编程模型

高速数据传输 – 高达 3.2 GB/s

异步操作

大 GPU 内存系统

Page 7: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

7

数百万基于CUDA GPUs

Total GPUs(millions)

25

50

2006 2007

专注于计算

GPU上的C语言

服务器到笔记本PC

Page 8: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

8

TeslaTM

高性能计算

Quadro®

设计和创作

GeForce®

娱乐

Page 9: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

9

VMD/NAMD 分子动力学

http://www.ks.uiuc.edu/Research/vmd/projects/ece498/lecture/

240X 加速

计算生物学

Page 10: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

10

生物进化机

130X 的加速

模拟脑电波

感观计算: 视觉,嗅觉

EvolvedMachines

Page 11: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

11

Hanweck合作伙伴

VOLERA、实时期权隐含波动引擎

单精度的准确结果

在不到1秒钟的时间内,评估所有美国上市的股票期权

www.hanweckassoc.com

Page 12: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

12

LIBOR应用:Mike Giles和Su Xiaoke

牛津大学计算实验室

带有互换期权投资组合的LIBOR模型

80个初始期货汇率和距离到期日的40时间步长

用伴随方法计算80Delta

No Greeks Greeks

Intel Xeon 18.1s - 26.9s -

ClearSpeed Advance

2 CSX600

2.9s 6x 6.4s 4x

NVIDIA 8800 GTX 0.045s 400x 0.18s 149x

可在此处获得源代码和论文:

http://web.comlab.ox.ac.uk/oucl/work/mike.giles/hpc

“CUDA代码性能非凡”

-Mike Giles

Page 13: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

13

Manifold 8地理信息

从Manifold 8特色列表中:…过去要达完成CUDA要求的应用程序往往需要数十秒甚至几分钟的时间,而现在只需短短百分之几秒的时间就能完成. … CUDA将会开启几乎所有GIS计算的未来

从用户手册中:“NVIDIA CUDA …是于微处理器的发明之后很有可能成为计算机领域一大革命性的事件。”

Page 14: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

14

N体天体物理学

http://progrape.jp/cs/

天体物理学研究

在标准PC上实现1 GF

在GeForce 8800GTX上300+ GF

比GRAPE-6Af 定制的仿真计算机更快

视频演示

Page 15: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

15

17X with MATLAB CPU+GPU

Pseudo-spectral simulation of 2D Isotropic turbulence

Matlab: 科学的语言

http://www.amath.washington.edu/courses/571-winter-2006/matlab/FS_2Dturb.m

http://developer.nvidia.com/object/matlab_cuda.html

Page 16: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

CUDA 编程模型介绍

Page 17: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

17

GPU 计算

GPU 是大规模并行计算NVIDIA G80: 128 个处理器

支持成千上万个活动线程度 (12,288 on G80)

GPU 计算需要一个编程模型, 能有效地表达这种并行最重要, 数据并行

CUDA 实现了这样一个编程模型

Page 18: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

18

CUDA 内核和线程

程序的并行部分在设备上执行, 这称为内核一次执行一个内核

许多线程执同一内核

CUDA 和 CPU 线程的区别CUDA 线程是超轻量级

非常小的创建开销

立即切换

CUDA 使用 1000 线程来获得效率多核CPU 只使用很少

定义:

设备 = GPU; 主机 = CPU

内核 = 运行在设备上的的函数

Page 19: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

19

并行线程阵列

一组线程阵列执行同一CUDA 内核所有线程运行相同的代码

每个线程都有自己的ID, 用来计算内存地址和做控制决策

0 1 2 3 4 5 6 7

float x = input[threadID];

float y = func(x);

output[threadID] = y;

threadID

Page 20: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

20

线程协作

不可缺少: 线程可能需要协作

线程协作是是有价值的共享结果节省计算

同步

共享内存访问

带宽的急剧降低

线程协作是CUDA的强大性能之一

Page 21: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

21

float x = input[threadID];

float y = func(x);

output[threadID] = y;

threadID

Thread Block 0

……

float x = input[threadID];

float y = func(x);

output[threadID] = y;

Thread Block 0

float x = input[threadID];

float y = func(x);

output[threadID] = y;

Thread Block N - 1

线程块:可伸缩的协作

把整个线程阵列分成许多块(Block)

块中的线程通过共享 内存

不同块中的线程不能协作

使得程序可以在任意数目的处理器上透明伸缩!

0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7

Page 22: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

22

透明伸缩

任何时候硬件都可以自由地在处理器上调度线程块

内核的伸缩可以跨任何数目的并行处理器

Device

Block 0 Block 1

Block 2 Block 3

Block 4 Block 5

Block 6 Block 7

Kernel grid

Block 0 Block 1

Block 2 Block 3

Block 4 Block 5

Block 6 Block 7

Device

Block 0 Block 1 Block 2 Block 3

Block 4 Block 5 Block 6 Block 7

Page 23: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

23

CUDA 编程模型

内核被一个 grid 的线程块执行(thread block)

线程块(thread block)是可以相互协作的线程的批处理,通过:

通过共享内存共享数据

同步它们的运行

不同块的线程不能协作

Host

Kernel

1

Kernel

2

Device

Grid 1

Block

(0, 0)

Block

(1, 0)

Block

(2, 0)

Block

(0, 1)

Block

(1, 1)

Block

(2, 1)

Grid 2

Block (1, 1)

Thread

(0, 1)

Thread

(1, 1)

Thread

(2, 1)

Thread

(3, 1)

Thread

(4, 1)

Thread

(0, 2)

Thread

(1, 2)

Thread

(2, 2)

Thread

(3, 2)

Thread

(4, 2)

Thread

(0, 0)

Thread

(1, 0)

Thread

(2, 0)

Thread

(3, 0)

Thread

(4, 0)

Page 24: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

24

处理器 执行计算线程

线程执行管理器发送线程

128 线程处理器分成16组多处理器(SM)

并行数据缓存 (共享内存) 使线程协作

G80 设备

Thread Execution Manager

Input Assembler

Host

Parallel

Data

Cache

Global Memory

Load/store

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Parallel

Data

Cache

Parallel

Data

Cache

Thread Processors

Page 25: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

25

线程和块 ID

线程和 Block 都有 ID每个线程能决定什么数据执行

Block ID: 1D or 2D

Thread ID: 1D, 2D, or 3D

简化内存寻址,当处理多维数据时

图像处理

偏微分方程

Device

Grid 1

Block

(0, 0)

Block

(1, 0)

Block

(2, 0)

Block

(0, 1)

Block

(1, 1)

Block

(2, 1)

Block (1, 1)

Thread

(0, 1)

Thread

(1, 1)

Thread

(2, 1)

Thread

(3, 1)

Thread

(4, 1)

Thread

(0, 2)

Thread

(1, 2)

Thread

(2, 2)

Thread

(3, 2)

Thread

(4, 2)

Thread

(0, 0)

Thread

(1, 0)

Thread

(2, 0)

Thread

(3, 0)

Thread

(4, 0)

Page 26: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

26

内核内存访问

寄存器(Register)

全局内存 (external DRAM)内核的输入输出数据存放在这里片下,较大非高速缓存

共享内存 (Parallel Data Cache)被同一块内的线程共享片上,较小与寄存器同样快

Grid

Global

Memory

Block (0, 0)

Shared Memory

Thread (0, 0)

Registers

Thread (1, 0)

Registers

Block (1, 0)

Shared Memory

Thread (0, 0)

Registers

Thread (1, 0)

Registers

Host

主机可以读写全局内存但不能读写共享内存

Page 27: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

27

执行模型

内核以Grid执行一个内核一次执行

一个Block 执行在一个流式多处理器上 (SM)

不需要移动

多个Block 可以同时驻留在一个 SM 上控制限制(G8X/G9X GPUs):

每个SM最多 8 并发 Block

每个SM最多 768 并发线程

数目进一步受到SM资源的限制寄存器文件在所有的驻留线程中分配

共享内存在所有的驻留线程块中分配

Page 28: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

28

CUDA 相对传统 GPGPU的优势(传统GPGPU是通过图形API编程GPU)

随机访问字节内存线程可访问内存任何地方

无限制访问内存线程可根据需要读写多个内存位置

共享内存 (Block) 和线程同步线程可以协作把数据装入共享内存

然后任何线程可以访问共享内存的任何位置

较低的学习曲线只是对C的一些扩展

不需要图形的知识

没有图形API的额外开销

Page 29: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

29

CUDA 模型总结

成千上万的并发轻量级线程没有转换开销

隐藏指令和内存延迟

共享内存用户可管理的L1缓存

块内线程可通讯和协作

随机访问全局内存任何线程可读写任何位置

最新一代的硬件:多达128个流式处理器

Memory Location Cached Access Scope (“Who?”)

Shared On-chip N/A Read/write All threads in a block

Global Off-chip No Read/write All threads + host

Page 30: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

CUDA编程

基础篇

Page 31: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

31

CUDA 基础篇纲要

建立和执行GPU代码:

GPU 内存管理

GPU 内核的执行

GPU代码的一些细节

一些其他的特性:

向量类型

管理多个GPU,多个CPU线程

检查CUDA错误

CUDA 事件 API

编译路径

注意:只覆盖基本特性更多的API函数参考编程指南

Page 32: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

32

管理内存

主机 (CPU) 管理设备 (GPU) 内存:

分配 / 释放

拷贝数据

对设备内存使用 global 和 constant

共享内存 (片上) 静态分配

主机管理纹理数据:

存储在 GPU 上

利用纹理缓存、过滤和钳位的优势( texture caching /

filtering / clamping)

主机管理固定CPU内存 (不可页交换) :

分配 / 释放

Page 33: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

33

GPU 内存分配 / 释放

cudaMalloc(void ** pointer, size_t nbytes)

cudaMemset(void * pointer, int value, size_t count)

cudaFree(void* pointer)

int n = 1024;

int nbytes = 1024*sizeof(int);

int *d_a = 0;

cudaMalloc( (void**)&d_a, nbytes );

cudaMemset( d_a, 0, nbytes);

cudaFree(d_a);

Page 34: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

34

数据拷贝

cudaMemcpy (void *dst, void *src, size_t nbytes, enum cudaMemcpyKind direction);

direction描述数据拷贝方向

阻塞CPU线程: 拷贝完成后返回

不开始拷贝直到前一个CUDA调用完成

cudaMemcpyAsync(..., cudaStream_t streamId)

主机内存必须固定 (用 cudaMallocHost 分配)

立即返回

不开始拷贝直到前一个CUDA用streamId调用完成或0完成

enum cudaMemcpyKindcudaMemcpyHostToDevice

cudaMemcpyDeviceToHost

cudaMemcpyDeviceToDevice

Page 35: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

35

练习 1

我们开始进入CUDA编程

在练习 1 你将学习使用 cudaMalloc 和 cudaMemcpy

Page 36: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

36

在GPU执行代码

C 函数的限制只能访问GPU内存没有参数的变量数目 (“varargs”)

没有静态变量

必须用限定词声明__global__ : 在主机(CPU)代码中调用,

不能从设备(GPU)代码中调用必须返回空 void

__device__ :在其他GPU代码中调用,

不能从主机CPU代码中调用

__host__ : 只能被CPU执行,从主机调用

__host__ 和 __device__ 联合使用

例如:过载操作符编译器将产生 CPU 和 GPU 代码

Page 37: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

37

发射GPU上的内核

修改的C函数调用语法:kernel<<<dim3 grid, dim3 block, int smem, int stream>>>(…)

执行配置 (“<<< >>>”):

grid 维数: x 和 y

线程块维数: x, y, 和 z

共享内存: 每个块的外部声明的无大小的smem变量的字节数

可选,缺省0

stream ID

可选,缺省0

dim3 grid(16, 16);

dim3 block(16,16);

kernel<<<grid, block, 0, 0>>>(...);

kernel<<<32, 512>>>(...);

Page 38: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

38

CUDA 内置的设备变量

所有 __global__ 和 __device__ 函数可以访问这些自动定义的变量

dim3 gridDim;

Grid 的块维数 (gridDim.z不使用)

dim3 blockDim;

Block的线程维数

dim3 blockIdx;

Grid 中的Block 索引

dim3 threadIdx;

Block 中的线程索引

Page 39: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

39

最小的 Kernel

__global__ void minimal( int* d_a)

{

*d_a = 13;

}

__global__ void assign( int* d_a, int value)

{

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

d_a[idx] = value;

} Common Pattern!

Page 40: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

40

2D数据的最小 Kernel

__global__ void assign2D(int* d_a, int w, int h, int value)

{

int iy = blockDim.y * blockIdx.y + threadIdx.y;

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

int idx = iy * w + ix;

d_a[idx] = value;

}

...

assign2D<<<dim3(64, 64), dim3(16, 16)>>>(...);

Page 41: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

41

练习 2: 你的第一个 CUDA kernel

在这个练习中,你要写并执行一个简单的 CUDA kernel

Page 42: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

42

主机同步

所有 kernel 发射都是异步的控制立即返回到CPU

在以前所有CUDA调用完成后,kernel 才执行

cudaMemcpy 是异步的拷贝完成后控制立即返回到CPU

在以前所有CUDA调用完成后, 拷贝开始

cudaThreadSynchronize()

在以前所有CUDA调用完成后, 开始阻塞

异步 API 提供:

GPU CUDA-call streams

non-blocking cudaMemcpyAsync

Page 43: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

43

实例:数组元素增量

CPU program CUDA program

void increment_cpu(float *a, float b, int N)

{

for (int idx = 0; idx<N; idx++)

a[idx] = a[idx] + b;

}

void main()

{

.....

increment_cpu(a, b, N);

}

__global__ void increment_gpu(float *a, float b, int N)

{

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

if (idx < N)

a[idx] = a[idx] + b;

}

void main()

{

…..

dim3 dimBlock (blocksize);

dim3 dimGrid( ceil( N / (float)blocksize) );

increment_gpu<<<dimGrid, dimBlock>>>(a, b, N);

}

Page 44: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

44

实例: 数组元素增量

Increment N-element vector a by scalar b

Let’s assume N=16, blockDim=4 -> 4 blocks

blockIdx.x=0

blockDim.x=4

threadIdx.x=0,1,2,3

idx=0,1,2,3

blockIdx.x=1

blockDim.x=4

threadIdx.x=0,1,2,3

idx=4,5,6,7

blockIdx.x=2

blockDim.x=4

threadIdx.x=0,1,2,3

idx=8,9,10,11

blockIdx.x=3

blockDim.x=4

threadIdx.x=0,1,2,3

idx=12,13,14,15

int idx = blockDim.x * blockId.x + threadIdx.x;

will map from local index threadIdx to global index

NB: blockDim should be >= 32 in real code, this is just an example

Page 45: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

45

实例: 主机// allocate host memory

unsigned int numBytes = N * sizeof(float)

float* h_A = (float*) malloc(numBytes);

// allocate device memory

float* d_A = 0;

cudaMalloc((void**)&d_A, numbytes);

// copy data from host to device

cudaMemcpy(d_A, h_A, numBytes, cudaMemcpyHostToDevice);

// execute the kernel

increment_gpu<<< N/blockSize, blockSize>>>(d_A, b);

// copy data from device back to host

cudaMemcpy(h_A, d_A, numBytes, cudaMemcpyDeviceToHost);

// free device memory

cudaFree(d_A);

Page 46: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

46

变量限定符 (GPU 代码)

__device__存储在设备内存中 (大, 高延迟, 非缓存)

用cudaMalloc分配(暗指__device__ 限定符)

可被所有线程访问寿命: 整个应用程序

__constant__与 __device__ 相同, 但被缓存并GPU只读通过 cudaMemcpyToSymbol(...) 调用被CPU写寿命: 整个应用程序

__shared__存储在片上共享内存中 (延迟非常低)

可被相同线程块内的所有线程访问寿命: Kernel

无限制的变量:存储在寄存器中的标量和内置的向量类型超过4个元素的数组存储在设备内存中

Page 47: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

47

CUDA 内存空间

每个线程可以:

读/写每个thread registers

读/写每个thread local memory

读/写每个block shared memory

读/写每个grid global memory

只读每个grid constant memory

只读每个grid texture memory

Grid

Constant

Memory

Texture

Memory

Global

Memory

Block (0, 0)

Shared Memory

Local

Memory

Thread (0, 0)

Registers

Local

Memory

Thread (1, 0)

Registers

Block (1, 0)

Shared Memory

Local

Memory

Thread (0, 0)

Registers

Local

Memory

Thread (1, 0)

Registers

Host主机可以读写全局,常数和纹理内存(存储在DRAM中)

Page 48: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

48

CUDA 内存空间之前介绍了全局和共享内存

最重要,最常用

Local , Constant和Texture是为了方便和性能Local: 编译器自动分配的数组变量

Constant: 用于均匀访问的只读数据

被缓存 (参见编程指南)

Texture: 用于空间连续的随机访问的只读数据

被缓存 (参见编程指南)

提供地址clamping 和wrapping

Memory Location Cached Access Scope (“Who?”)

Local Off-chip No Read/write One thread

Shared On-chip N/A Read/write All threads in a block

Global Off-chip No Read/write All threads + host

Constant Off-chip Yes Read All threads + host

Texture Off-chip Yes Read All threads + host

Page 49: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

49

内置的向量类型

可以在GPU和CPU代码中使用

[u]char[1..4], [u]short[1..4], [u]int[1..4],

[u]long[1..4], float[1..4]

x, y, z, w 域的结构:

uint4 param;

int y = param.y;

dim3

基于 uint3

用来描述维数

缺省值 (1,1,1)

Page 50: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

50

线程同步函数

void __syncthreads();

同步块中的所有线程产生壁垒( barrier)同步指令

没有线程可以通过这个壁垒( barrier )直到块中的所有线程到达它

当访问共享内存时,用来避免 RAW / WAR / WAW 危险

允许在条件代码中,并只有这个条件在整个线程块中时统一的

Page 51: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

51

GPU 原子整数操作

在全局内存中对整数的原子操作:

Associative operations on signed/unsigned ints

add, sub, min, max, ...

and, or, xor

Increment, decrement

Exchange, compare and swap

需要计算能力1.1的硬件

Page 52: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

52

设备管理

CPU 可以查询和选择GPU设备cudaGetDeviceCount( int *count )

cudaSetDevice( int device )

cudaGetDevice( int *current_device )

cudaGetDeviceProperties( cudaDeviceProp* prop,

int device )

cudaChooseDevice( int *device, cudaDeviceProp* prop )

多GPU的设置:

缺省使用设备0

一个CPU线程只能控制一个GPU

多CPU线程可以控制相同的GPU

– 驱动串行执行调用

Page 53: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

53

多CPU线程和 CUDA

一个CPU线程分配的CUDA 资源只被相同CPU线程中的CUDA调用所利用

例外:

CPU thread 2 分配GPU内存,存储在 p

thread 3 发出一个访问p CUDA调用

Page 54: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

54

CUDA 错误报告给 CPU

所有CUDA返回错误代码:

kernel 发射例外

cudaError_t 类型

cudaError_t cudaGetLastError(void)

返回最后的错误代码 (no error has a code)

char* cudaGetErrorString(cudaError_t code)

返回一个非空的字符串描述错误

printf(“%s\n”, cudaGetErrorString( cudaGetLastError() ) );

Page 55: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

55

CUDA 事件 API

事件插入进CUDA调用流中

使用脚本:测量CUDA调用的时间 (clock cycle precision)

查询异步CUDA调用的状态

阻塞CPU直到事件以前的CUDA调用完成

在CUDA SDK 中有异步API 的实例

cudaEvent_t start, stop;

cudaEventCreate(&start); cudaEventCreate(&stop);

cudaEventRecord(start, 0);

kernel<<<grid, block>>>(...);

cudaEventRecord(stop, 0);

cudaEventSynchronize(stop);

float et;

cudaEventElapsedTime(&et, start, stop);

cudaEventDestroy(start); cudaEventDestroy(stop);

Page 56: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

56

编译 CUDA

NVCC

C/C++ CUDA

Application

PTX to Target

Compiler

G80 … GPU

Target code

PTX Code Virtual

Physical

CPU Code

Page 57: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

57

NVCC & PTX 虚拟机

EDG

区别GPU和CPU代码

Open64

产生 GPU PTX 汇编

Parallel Thread eXecution (PTX)

虚拟机和 ISA

编程模型

执行资源和状态

EDG

C/C++ CUDA

Application

CPU Code

Open64

PTX Code

ld.global.v4.f32 {$f1,$f3,$f5,$f7}, [$r9+0];mad.f32 $f1, $f5, $f3, $f1;

float4 me = gx[gtid];me.x += me.y * me.z;

Page 58: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

58

编译

任何包含CUDA语言扩展的源文件都必须用nvcc编译

NVCC 是一个 编译器驱动程序调用所有必要的工具和编译器,如 cudacc, g++, cl, ...

NVCC 可以输出:

C 代码 (CPU代码)

然后必须用另一个工具编译程序的剩余部分

或 PTX 目标代码

CUDA代码的可执行文件需要:CUDA 核心库 (cuda)

CUDA 运行库 (cudart)

如果使用运行(runtime )API

装载 cuda 库

Page 59: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

59

练习 3: 反转一个小数组

给定一个输入数组,反转它

在这部分, 你将反转一个小数组单个线程块的大小

Page 60: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

60

练习 3: 反转一个大数组

给定一个大输入数组,反转它

这需要发射许多线程块

Page 61: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

让我们开始

Page 62: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

62

获得CUDA

CUDA Zone: http://nvidia.com/cuda

编程指南和其他文档

工具包和SDK::

Windows

Linux

MacOS

插件

论坛

代码范例

Page 63: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

63

来参加课程!

UIUC ECE498AL – 大规模并行处理器编程(http://courses.ece.uiuc.edu/ece498/al/)

David Kirk (NVIDIA) 和 Wen-mei Hwu (UIUC) 共同讲授

CUDA 编程, GPU 计算, 实验练习和项目

讲稿和录音

Page 64: NVIDIA CUDA 软件和 GPU 并行计算架构 - pudn.comread.pudn.com/downloads103/sourcecode/mpi/425099/CUDA... · 2008-03-27 · (传统GPGPU是通过图形API编程GPU) 随机访问字节内存

© NVIDIA Corporation 2006-2008

64

问题?