30.04.2014 Views

NVIDIA CUDA 计算统一设备架构

NVIDIA CUDA 计算统一设备架构

NVIDIA CUDA 计算统一设备架构

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

程 指 南 , 版<br />

<strong>NVIDIA</strong> <strong>CUDA</strong><br />

计 算 统 一 设 备 架 构<br />

编 程 指 南<br />

版 本 2.0<br />

6 / 7 / 2008<br />

<strong>CUDA</strong> 编<br />

i<br />

本 2.0


ii <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


目<br />

录<br />

1<br />

2 3 第<br />

第 4<br />

iii<br />

.......................................................................................................................................................... vi<br />

................................................................................................................................................... 1<br />

1.1 ............................................................................................................... 1<br />

1.2<br />

并 编 模<br />

GPU: ........................................................................................... 1<br />

1.3 .................................................................................................................................................. 3<br />

度 并 行 化 的 多 线 程 、 众 核 处 理 器 图 表 目<br />

...........................................................................................................................................<br />

录<br />

4<br />

<strong>CUDA</strong>:<br />

2.1 ..........................................................................................................................................<br />

介<br />

4<br />

2.2 ...................................................................................................................................... 6<br />

2.3 ..............................................................................................................................................<br />

可<br />

7<br />

伸 缩 行 程 型 高<br />

器 层 次 结 构 文 档 结<br />

2.4<br />

构<br />

...................................................................................................................................................... 8<br />

2.5 ..................................................................................................................................................<br />

备 章<br />

9<br />

型<br />

GPU ....................................................................................................................................... 10<br />

3.1<br />

栈 线<br />

SIMT<br />

程<br />

...................................................................................<br />

层<br />

10<br />

次 结 构 存 宿 主 和 设<br />

3.2 ................................................................................................................................................ 12<br />

3.3 ................................................................................................................................................<br />

储<br />

享 存 储 器 的 一 组 多 处 理 器 软<br />

12<br />

件<br />

......................................................................................................................... 13<br />

4.1 C<br />

设 备 计<br />

................................................................................................................................<br />

算<br />

13<br />

能 力 实 具 有 片<br />

4.2<br />

上<br />

................................................................................................................................................ 13<br />

4.2.1 .........................................................................................................................<br />

现 共<br />

展 多<br />

13<br />

个<br />

4.2.1.1 __device__........................................................................................................................ 13<br />

4.2.1.2<br />

扩 展 模<br />

__global__<br />

式<br />

........................................................................................................................<br />

切<br />

14<br />

换<br />

4.2.1.3 __host__............................................................................................................................ 14<br />

4.2.1.4 编<br />

..................................................................................................................................<br />

程<br />

14<br />

4.2.2 ......................................................................................................................... 14<br />

语<br />

4.2.2.1<br />

言<br />

__device__........................................................................................................................<br />

语<br />

14<br />

言<br />

4.2.2.2<br />

函<br />

__constant__<br />

数<br />

..................................................................................................................... 14<br />

4.2.2.3 __shared__........................................................................................................................ 15<br />

4.2.2.4<br />

章<br />

..................................................................................................................................<br />

口<br />

15<br />

4.2.3 ..................................................................................................................................... 16<br />

的 扩<br />

4.2.4<br />

类<br />

.....................................................................................................................................<br />

型<br />

16<br />

4.2.4.1 gridDim............................................................................................................................. 16<br />

限<br />

4.2.4.2<br />

定<br />

blockIdx<br />

符<br />

............................................................................................................................<br />

变<br />

16<br />

4.2.4.3 blockDim .......................................................................................................................... 16<br />

4.2.4.4 threadIdx ........................................................................................................................... 16<br />

4.2.4.5 warpSize ........................................................................................................................... 17<br />

4.2.4.6 17<br />

制<br />

4.2.5<br />

量<br />

17<br />

4.2.5.1 __noinline__ ..................................................................................................................... 17<br />

4.2.5.2 #pragma unroll.................................................................................................................. 17<br />

限 行 配<br />

4.3<br />

置 内 执<br />

18<br />

4.3.1 18<br />

量 变 置<br />

使<br />

4.3.1.1<br />

限 通 进<br />

char1、uchar1、char2、uchar2、char3、uchar3、char4、uchar4、short1、ushort1、short2、<br />

内<br />

简<br />

程 模 编<br />

应 用 程 序 编 程 接<br />

目<br />

录 ..........................................................................................................................................................<br />

置 向 量 类<br />

double2 ............................................................................................................................................ 18<br />

4.3.1.2 dim3 18<br />

4.3.2 18<br />

4.3.3 18<br />

4.3.4 19<br />

4.3.4.1 19<br />

类<br />

4.3.4.2 19<br />

数 纹 计 运 纹<br />

制 ..................................................................................................................................<br />

<strong>CUDA</strong> 编<br />

iii<br />

用 NVCC<br />

.............................................................................................................. 译 编 行<br />

.................................................................................................................................... 行 时 组 件 运 用<br />

型 .............................................................................................................................<br />

型 ........................................................................................................................<br />

ushort2、short3、ushort3、short4、ushort4、int1、uint1、int2、uint2、int3、uint3、int4、uint4、<br />

long1、ulong1、long2、ulong2、long3、ulong3、long4、ulong4、float1、float2、float3、float4、<br />

..................................................................................................................................... 数 函 学<br />

2.0 南 , 版 本 指 程<br />

..................................................................................................................................... 数 理 类 函 时<br />

型 .....................................................................................................................................<br />

.................................................................................................................. 考 声 明 参 理<br />

...................................................................................................... 纹 理 参 考 属 性 时 行


第 5<br />

4.4<br />

4.5<br />

设<br />

宿<br />

5.1 指<br />

4.3.4.3 20<br />

.................................................................................................................................... 20<br />

4.4.1 ..................................................................................................................................... 20<br />

4.4.2 ..................................................................................................................................... 20<br />

4.4.3 ..................................................................................................................................... 21<br />

同 步 数<br />

4.4.3.1 .................................................................................................. 21<br />

备<br />

4.4.3.2<br />

运<br />

<strong>CUDA</strong><br />

行<br />

...............................................................................................<br />

时<br />

21<br />

组<br />

4.4.4<br />

件<br />

..................................................................................................................................... 21<br />

4.4.5 Warp<br />

器 数<br />

vote<br />

学<br />

........................................................................................................................... 22<br />

的 纹 理 原 子 函 数 纹 理<br />

.................................................................................................................................... 22<br />

4.5.1 .....................................................................................................................................<br />

线<br />

22<br />

性<br />

4.5.1.1<br />

存<br />

..................................................................................................................................<br />

储<br />

22<br />

4.5.1.2 .............................................................................................................................. 23<br />

来 自 数 组<br />

设 备 函 数<br />

4.5.1.3 OpenGL ........................................................................................................... 23<br />

器 主<br />

4.5.1.4<br />

运<br />

Direct3D<br />

行<br />

..........................................................................................................<br />

时<br />

23<br />

4.5.1.5 .................................................................................................................. 23<br />

4.5.2<br />

组<br />

API.................................................................................................................................<br />

件<br />

24<br />

一 般 概 念<br />

并 发 执 行 存 储<br />

4.5.2.1 .............................................................................................................................. 24<br />

时 4.5.2.2 .......................................................................................................................... 24<br />

4.5.2.3 ...................................................................................................................... 25<br />

4.5.2.4<br />

互<br />

..............................................................................................................................<br />

操<br />

26<br />

作 性 异 步<br />

管 理 运 行<br />

4.5.2.5 .......................................................................................................................... 26<br />

理 初<br />

4.5.2.6<br />

始<br />

..................................................................................................................<br />

化<br />

27<br />

4.5.2.7 OpenGL ...........................................................................................................<br />

理 设<br />

28<br />

备<br />

4.5.2.8 Direct3D .......................................................................................................... 28<br />

管 理 存 储 器 流 管<br />

4.5.2.9 ........................................................................................... 29<br />

作 性 事<br />

4.5.3<br />

件<br />

API.............................................................................................................................<br />

管<br />

30<br />

4.5.3.1 .............................................................................................................................. 30<br />

备 模 拟 模 式 进 行 调 试 纹<br />

4.5.3.2<br />

理<br />

..........................................................................................................................<br />

参<br />

30<br />

考 互 操<br />

4.5.3.3 ...................................................................................................................... 30<br />

使<br />

4.5.3.4<br />

用<br />

..........................................................................................................................<br />

设<br />

31<br />

4.5.3.5 .......................................................................................................................... 31<br />

驱<br />

4.5.3.6<br />

动<br />

......................................................................................................................<br />

程<br />

32<br />

序 初 始 化<br />

制 设 备<br />

4.5.3.7 .............................................................................................................................. 33<br />

器 管 理 上<br />

4.5.3.8<br />

下<br />

..........................................................................................................................<br />

文<br />

33<br />

4.5.3.9 .................................................................................................................. 34<br />

模<br />

4.5.3.10<br />

块<br />

OpenGL ......................................................................................................... 34<br />

执 行 控<br />

考 管 理 存 储<br />

4.5.3.11 Direct3D ........................................................................................................ 35<br />

流<br />

.........................................................................................................................................<br />

管<br />

36<br />

理<br />

................................................................................................................................................ 36<br />

5.1.1<br />

性 事<br />

............................................................................................................................. 36<br />

件 管 理 5.1.1.1 .......................................................................................................................... 36<br />

纹 理 参 互<br />

5.1.1.2<br />

操<br />

......................................................................................................................<br />

作<br />

37<br />

5.1.1.3 ...................................................................................................................... 37<br />

令 南<br />

5.1.1.4 38<br />

制 流 令 性 能<br />

指 令 指<br />

5.1.2 38<br />

令<br />

5.1.2.1 38<br />

5.1.2.2<br />

数<br />

44<br />

5.1.2.3 44<br />

学 吞<br />

5.1.2.4 44<br />

指<br />

5.1.2.5 44<br />

5.1.2.6<br />

控<br />

49<br />

50<br />

存 量 吐<br />

同 器 储<br />

本 全 存<br />

寄 共 纹 常<br />

性 能 指 章<br />

5.2 每<br />

<strong>CUDA</strong> 性 存 储 器 的 纹 理 与 来 自 线 自<br />

.................................................... 纹 理 的 组<br />

iv <strong>CUDA</strong> 编<br />

.......................................................................................................................... 令 指 步<br />

......................................................................................................................... 带 宽 器 储<br />

...................................................................................................................... 储 器 存 地<br />

...................................................................................................................... 储 器 存 局<br />

2.0 南 , 版 本 指 程<br />

...................................................................................................................... 储 器 存 量<br />

...................................................................................................................... 器 享 存 储 理<br />

器 ......................................................................................................................<br />

.............................................................................................................................. 器 存<br />

................................................................................................................................ 的 线 程 数 量 块 个


程 指 南 , 版<br />

5.3<br />

5.4<br />

5.5<br />

6.1<br />

整 章 宿<br />

6.2<br />

6.3<br />

纹<br />

源 概<br />

50<br />

......................................................................................... 51<br />

................................................................................................................................ 51<br />

................................................................................................................................. 53<br />

........................................................................................................................................................ 53<br />

............................................................................................................................................ 54<br />

器 读 取 的 对 比 体 性 能 优 化 策 略 例 述 理 拾 取<br />

............................................................................................................................................<br />

与<br />

55<br />

6.3.1 Mul()............................................................................................................................................<br />

全<br />

55<br />

局<br />

6.3.2<br />

或<br />

Muld()..........................................................................................................................................<br />

常<br />

55<br />

.........................................................................................................................................<br />

量 储 存<br />

范 明 说 码 代 单 清 6<br />

A 57<br />

第<br />

A.1 ............................................................................................................................................... 57<br />

A.1.1 1.0 ................................................................................................................ 57<br />

A.1.2 1.1 ................................................................................................................ 58<br />

A.1.3 1.2 ................................................................................................................ 58<br />

A.1.4 1.3 ................................................................................................................ 58<br />

附 录 一<br />

A.2<br />

范<br />

............................................................................................................................................... 58<br />

B ................................................................................................................................. 60<br />

技<br />

力 的 规 范 B.1 .................................................................................................................................... 60<br />

函 数 B.1.1 ......................................................................................................................... 60<br />

B.1.2 计<br />

.........................................................................................................................<br />

算<br />

62<br />

B.1.3 ..................................................................................................................................... 63<br />

能 浮<br />

B.2<br />

点<br />

.................................................................................................................................... 63<br />

附 录 标 准 通 用 B.2.1 ......................................................................................................................... 64<br />

B.2.2<br />

数 学 ......................................................................................................................... 65<br />

B.2.3 ..................................................................................................................................... 65<br />

C ......................................................................................................................................... 66<br />

点 函 数 设 备 运<br />

C.1 ................................................................................................................................................ 66<br />

C.1.1<br />

行 时 组 单<br />

atomicAdd() ................................................................................................................................ 66<br />

C.1.2 atomicSub()................................................................................................................................. 66<br />

C.1.3 atomicExch()............................................................................................................................... 66<br />

C.1.4 atomicMin() ................................................................................................................................ 66<br />

件<br />

C.1.5 atomicMax()................................................................................................................................ 67<br />

C.1.6 atomicInc() .................................................................................................................................. 67<br />

C.1.7 atomicDec()................................................................................................................................. 67<br />

C.1.8 atomicCAS() ............................................................................................................................... 67<br />

数 函 数 函 子 数 函 型 整 浮 度 精 双 学 数 原 录 附<br />

阵 乘 法 示 矩<br />

规 般 规 术<br />

能 算<br />

C.2 位<br />

D.1 最 纹<br />

D.2<br />

D.3 表 线<br />

67<br />

C.2.1 atomicAnd() ................................................................................................................................ 67<br />

C.2.2 atomicOr()................................................................................................................................... 68<br />

C.2.3 atomicXor()................................................................................................................................. 68<br />

69<br />

69<br />

70<br />

70<br />

.................................................................................................................... 设 备 间 的 数 据 传 输 和 主<br />

............................................................................................................................................ 函 数 辑 逻<br />

附<br />

......................................................................................................................................... 取 拾 理<br />

<strong>CUDA</strong> 编<br />

v<br />

录 D<br />

........................................................................................................................................... 采 样 性 过 点 近<br />

滤 ...............................................................................................................................................<br />

................................................................................................................................................... 找 查<br />

本 2.0


图 表 目 录<br />

CPU<br />

1-2. 图 和<br />

GPU<br />

2-1. .......................................... 程 块 网 格 图 中<br />

线<br />

存<br />

异<br />

的 更 多 晶 体 管 用 于 数 据 处 的<br />

...... ......... ..... .............. .....................2 宽<br />

...... .............. .......... .............. .............. .....................2 理<br />

....... ..................... ...................................................6<br />

器 层 次 结 储<br />

<strong>CUDA</strong><br />

................................................................... 型 软<br />

硬<br />

库<br />

2-2.<br />

2-3.<br />

2-4.<br />

3-1. 4-1. 5-1.<br />

5-2. 存 图<br />

................................. .............. ...................................................................7 构<br />

............. .............. .............. ....................................8<br />

................ .............. .............. ..................... .............. .. ...................................9 栈<br />

.............. ...........................................11<br />

......................................................... 理<br />

.............. ....... ......... ...........................31<br />

................... 例<br />

.............. .............. .............. .. ........ ..40<br />

.... 例<br />

............................................... 程 件 件 模 构 编<br />

文 管 储 器 合 并 后 的 存 储 器 访 问 模 式 示 为 计 算 能 力 设 备 进 行 存 储 器 合 并 的 全 局 存 储 器 访 问 模 式 示 上 下<br />

的 或 未<br />

计<br />

无<br />

无<br />

1.0<br />

或 是<br />

41<br />

... .42 例<br />

1.1<br />

.............. .............. .............. ...............48<br />

用 广 播 机 制 的 共 享 存 储 器 读 取 访 问 模 式 示 有<br />

5-8. 使 图<br />

矩<br />

..... .............. ............ .. .. .........43 例<br />

.............. .............. .............. .............. ......46<br />

.............. .............. .............. .............. ......47<br />

... .............. .............. .............. ...............49 例<br />

........................................................... .............. .............. ....................................53 法<br />

图 1-1.<br />

GPU<br />

每 秒 浮 点 运 算 次 数 和 存 储 器 带<br />

图 5-3.<br />

1.0 算 能 力 是 计 为<br />

1.1<br />

设 备 进 行 存 储 器 合 并 的 全 局 存 储 器 访 问 模 式 示<br />

图 5-5.<br />

... 体 冲 突 的 共 享 存 储 器 访 问 模 式 示 例 储 存<br />

图 5-4.<br />

1.2 力 为 能 算<br />

更 高 的 设 备 的 全 局 存 储 器 访 问 示<br />

图 5-6.<br />

... 体 冲 突 的 共 享 存 储 器 访 问 模 式 示 例 储 存<br />

图 5-7.<br />

......... 体 冲 突 的 共 享 存 储 器 访 问 模 式 示 例 储 存<br />

图 6-1.<br />

阵 乘<br />

vi <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


核 (manycore) 众<br />

程 指 南 , 版<br />

图<br />

所 已<br />

(language<br />

(runtime<br />

第 1 章 简 介<br />

1.1 <strong>CUDA</strong>: 可 伸 缩 并 行 编 程 模 型<br />

<strong>CUDA</strong> 是<br />

<strong>CUDA</strong> 的<br />

和<br />

GPU 的<br />

种 并 行 编 程 模 型 和 软 件 环 境 , 用 于 应 对 这 种 挑 战 。 而 对 于 熟 绝 一<br />

语<br />

图<br />

定 律 , 其 并 行 性 还 会 不 断 扩 展 。 这 给 我 们 带 来 了 严 峻 的 挑 战 —— 我 们 需 要 开 发 出 可 透 明 地 扩 展 并 行 语 言 等 标 准 编 程 语 言 的 尔<br />

(barrier synchronization),<br />

CPU 核 多<br />

出 现 意 味 着 主 流 处 理 器 芯 片 已 进 入 并 行 时 代 。 此 外 , 根 据 摩<br />

物 理 处 理 器 数 量 。<br />

时 通 过 在 任 何 可 用 处 理 器 内 核 上 处 理 各 子 问 题 来 支 持 透 明 的 可 伸 缩 性 : 因 而 , 编 译<br />

3D 应 用 软 件 , 以 利 用 日 益 增 加 处 理 器 内 核 数 量 , 这 种 情 况 正 如 行 性 以 支 持 配 备 各 种 数 量 的 内 核 的 众 的 性<br />

核 GPU。<br />

形 应 用 程 序 透 明 地 扩 展 其 并<br />

C<br />

核 心 有 三 个 重 要 抽 象 概 念 : 组 层 次 结 构 、 共 享 存 储 器 、 栅 障 同 步 悉<br />

些 抽 象 提 供 了 细 粒 度 的 数 据 并 行 和 线 程 并 行 , 嵌 套 于 粗 粒 度 的 数 据 并 行 和 任 务 并 行 之 中 。 它 们 将 指 导 程 序 员 将 问 题 为 可 独 立 处 理 的 粗 粒 度 子 问 题 , 再 细 分 成 细 粒 度 的 片 段 , 以 便 通 过 协 作 的 方 法 并 行 解 决 。 这 样 的 分 解 以 允 许 线 程 在 解 决 子 问 题 时 协 作 为 目 的 设 计 了 编 程 语 言 的 表 达 方 式<br />

expressivity), 同 这<br />

system) 需 程<br />

1.2 GPU: 高 度 并 行 化 的 多 线 程 、 众 核 处 理 器<br />

<strong>CUDA</strong> 员 来 说 , 迅 速 掌 握 序 程<br />

难 事 。 非<br />

C 程 序 员 来 说 , 它 们 只 是 于 对<br />

的 一 个 极 小 扩 展 。 言<br />

形 永 无 尽 头 的 需 求 , 可 编<br />

发 展 成 为 一 种 高 度 并 行 化 的<br />

<strong>CUDA</strong> 的 后<br />

序 可 以 在 任 何 数 量 的 处 理 器 内 核 上 执 行 , 只 有 运 行 时 系 统<br />

要 了 解<br />

多 线 程 、 众 核 处 理 器 , 具 有 杰 出 的 计 算 能 力 和 极 高 的 存 储 器 带 宽 , 如<br />

。 示<br />

<strong>CUDA</strong> 编<br />

1<br />

3D 足 消 费 者 对 实 时 、 高 清 晰 度 的 满 为<br />

程 GPU<br />

图 1-1<br />

本 2.0


和<br />

和<br />

之<br />

,GPU 专<br />

(flow 如 control),<br />

的<br />

专 为 计 算 密 集 型 、 高 度 并 行 化 的 的 设 计 将 更 多 晶 体 管 用 于 数 据 处 理 , 而 非 数 据 缓 存 所 示 。 宽<br />

CPU<br />

CPU<br />

宽 的 每 秒 浮 点 运 算 次 数 和 存 储 器 带 图 1-1.<br />

GPU<br />

图 1-2<br />

GPU 中<br />

GPU<br />

GPU 点 能 力 之 所 以 存 在 这 样 的 差 异 , 原 因 就 在 于 浮 间<br />

,GPU 而 设 计 , 上 图 显 示 的 正 是 这 种 情 况 , 因 而<br />

(caching) 和 流 控 制 算 计<br />

具 体 地 说 有 极 高 的 计 算 密 度 ( 数 学 运 算 与 存 储 器 操 作 的 比 率 )。 由 于 所 有 数 据 元 素 都 执 行 相 同 的 程 序 , 因 此 对 精 密 更<br />

2 <strong>CUDA</strong> 解 决 可 表 示 为 数 据 并 计 算 的 问 题 —— 在 许 多 数 据 元 素 上 并 行 执 行 的 程 序 , 具 流 控 制 的 要 求 高 ; 由 于 在 许 多 数 据 元 素 上 运 行 , 且 具 有 较 高 的 计 算 密 度 , 因 而 可 通 过 计 算 来 隐 藏 存 储 器 访 问 延 迟 , 而 不 必 使 用 较 大 的 数 据 缓 存 。 编<br />

图 1-2.<br />

中 的 更 多 晶 体 管 用 于 数 据 处 理<br />

2.0 南 , 版 本 指 程


渲<br />

程 指 南 , 版<br />

的<br />

第<br />

列 的<br />

(texture 的 fetching)<br />

介 。 运 行 时 简<br />

。<br />

。。<br />

编<br />

。<br />

应 架<br />

<strong>CUDA</strong> 编<br />

GPU 基<br />

1.3 文 档 结 构<br />

3D 来 加 速 计 算 。 在 染 中 , 大 量 的 像 素 顶 点 集 将 映 射 到 并 行 线 程 。 类 似 地 , 图 像 和 媒 体 处 理 应 用 程 序 ( 如 渲 染 图 像 的 后 期 处 理 、 视 频 编 码 和 解 码 、 图 像 缩 放 、 立 体 视 觉 和 模 式 识 别 等 ) 可 将 图 像 块 和 像 素 映 射 到 并 行 处 理 线 程 。 实 际 上 , 在 图 像 渲 染 和 处 理 领 域 之 外 的 许 多 算 法 也 都 是 通 过 数 据 并 行 处 理 加 速 的 —— 从 普 通 信 号 处 理 或 物 理 仿 真 一 直 到 计 算 金 融 或 计 算 生 物 学 。 模 型<br />

型 , 可 显 著 加 用 程 序 。 模 程<br />

数 据 并 行 处 理 会 将 数 据 元 素 映 射 到 并 行 处 理 线 程 。 许 多 处 理 大 型 数 据 集 的 应 用 程 序 都 可 使 用 数 据 并 行 编 程<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

附 第 章 列 给 提<br />

文 档 分 为 以 下 几 个 章 节 : 和 的 编 程 模 型 实 现 。 本<br />

API<br />

提 供 如 何 实 现 最 高 性 能 的 一 些 指 南 和<br />

过 一 些 简 单 示 例 代 码 概 况 之 前 各 章 的 内 容 供 各 种 设 备 的 技 术 规 范 支 持 的 数 学 函 数 中 通<br />

更 多 纹 理 拾 取 出<br />

GPU 型 非 常 适 合 利 用 模 程<br />

<strong>NVIDIA</strong> 能 力 。 最 新 一 代 的 行 并<br />

于 Tesla<br />

A 在 附 录 ( 构<br />

<strong>CUDA</strong> 以 查 看 所 有 支 持 可 中<br />

GPU<br />

<strong>CUDA</strong> 支 持 ), 表<br />

速 <strong>CUDA</strong><br />

1<br />

是 <strong>CUDA</strong><br />

GPU<br />

2<br />

<strong>CUDA</strong> 述 概<br />

3<br />

GPU 绍 介<br />

4<br />

<strong>CUDA</strong> 绍 介<br />

持 的 原 子 函 数 。 支<br />

细 节<br />

5<br />

录 D<br />

6<br />

录 C<br />

录 A<br />

录 B<br />

举 <strong>CUDA</strong><br />

举 <strong>CUDA</strong><br />

<strong>CUDA</strong> 编<br />

3<br />

本 2.0


中<br />

个<br />

线<br />

线 声<br />

的<br />

设<br />

的<br />

和<br />

相<br />

次 语<br />

语 (declaration 使 specifier),<br />

个<br />

block)。 这<br />

是<br />

是<br />

的<br />

中 变<br />

和<br />

z)<br />

相<br />

语 。<br />

此 ID。<br />

x,D y ) 的<br />

第 2 章 编 程 模 型<br />

<strong>CUDA</strong> 允<br />

言 的 一 种 扩 展 , 在 调 用 此 类 函<br />

言 函 数 只 执 行 一 次 的 方 式 不 同<br />

的<br />

// Kernel definition<br />

__global__ void vecAdd(float* A, float* B, float* C)<br />

{<br />

}<br />

符 定 限 明<br />

(kernel)<br />

许 程 序 员 定 义 被 称 为 内 核<br />

C<br />

int main()<br />

{<br />

}<br />

// Kernel invocation<br />

vecAdd(A, B, C);<br />

C 数 , 这 是 对 函 言<br />

N , 它 将 由 时 数<br />

<strong>CUDA</strong> 的 同 不<br />

N 行 执 行 并 程<br />

C 与 普 通 的 这 ,<br />

__global__ 义 内 核 时 , 需 要 使 用 定 在<br />

:<br />

种 全 新 的 一 用<br />

__global__ void vecAdd(float* A, float* B, float* C)<br />

{<br />

int i = threadIdx.x;<br />

C[i] = A[i] + B[i];<br />

}<br />

可<br />

<strong>CUDA</strong> 定 每 次 调 用 的 指 法<br />

数 : 程<br />

int main()<br />

{<br />

// Kernel invocation<br />

vecAdd(A, B, C);<br />

}<br />

) 每 个 线 程 都 会 执 行 一 次 两 两 相 加 运 算 的<br />

行 内 核 的 每 个 线 程 都 会 被 分 配 一 个 独 特 的 线 程 ID, 执<br />

threadIdx 内 置 的 过 通<br />

量 在 内 核 中 访 问<br />

2.1 线 程 层 次 结 构<br />

执<br />

线 程 层 次 结 构<br />

N 示 例 代 码 将 大 小 为 下 以<br />

A 量 向<br />

B 量 向<br />

C 并 将 结 果 存 储 在 向 量 , 加<br />

行 vecAdd(<br />

__global__ void matAdd(float A[N][N], float B[N][N],<br />

float C[N][N])<br />

{<br />

int i = threadIdx.x;<br />

int j = threadIdx.y;<br />

C[i][j] = A[i][j] + B[i][j];<br />

}<br />

int main()<br />

{<br />

// Kernel invocation<br />

dim3 dimBlock(N, N);<br />

matAdd(A, B, C);<br />

}<br />

:<br />

(thread<br />

C<br />

构 成 一 维 、 二 维 或 三 维 线 程 块 储 在 矩 阵 , 程 线<br />

有<br />

。<br />

供 了 一 种 自 然 的 方 法 , 可 为 一 个 域 中 的 各 元 素 提<br />

threadIdx 便 起 见 , 我 们 将 方 为<br />

3 一 个 包 含 为 置<br />

分 量 的 向 量 , 因 而 可 使 用 一 维 、 二 维 或 三 维 索 引 标 识<br />

y, z)<br />

+ yD<br />

+ yD x + zD x D y)。 x);<br />

x,D y,<br />

4 <strong>CUDA</strong> 编<br />

NxN 计 算 , 如 向 量 、 矩 阵 或 字 段 。 下 面 的 示 例 代 码 将 大 小 为 用 调<br />

A 阵 矩<br />

B 阵 矩<br />

加 , 并 将 结 果 存<br />

(x,y) 块 来 说 , 索 引 为 维 二<br />

ID 的 程 线<br />

(x<br />

(D 大 小 为 于 对<br />

D<br />

的 三 维 块 来 说 , 索<br />

2.0 南 , 版 本 指 程<br />

ID 的 索 引 与 其 线 程 程 线<br />

(D 接 的 对 应 关 系 : 对 于 一 维 块 来 说 , 两 者 是 相 同 的 ; 对 于 大 小 为 直 着<br />

(x, 为 引<br />

ID 程 的 线 的<br />

(x


程 指 南 , 版<br />

变<br />

(shared<br />

(intrinsic 内 function) 在 来 memory)<br />

(grid),<br />

所<br />

缓<br />

变 语<br />

将 每 个 线 程 处 理 一 个 矩 阵 元 素 , 这 与 之 前 完 全 相 同 。 线 程 块 需 要 独 立 执 行 : 必 须 能 够 以 任 意 顺 序 执 行 —— 能 够 并 行 或 串 行 执 行 。 这 种 独 立 性 需 求 允 许 为 任 意 数 量 的 处 理 器 内 核 安 排 线 程 块 , 从 而 使 程 序 员 能 够 编 写 出 可 伸 缩 的 代 码 。<br />

个 网 格 内 的 线 程 块 通 常 是 由 所 处 理 的 数 据 大 小 限 定 的 , 而 不 是 由 系 统 中 的 处 理 器 数 量 决 定 的 , 前 者 可 以 远 远 超 过 后 者 的 数 量 。 一<br />

建 函 数<br />

共 享 数 据 , 并 同 步 其 执 行 来 协 调 存<br />

屏 障 的 作 用 , 块 中 的 所 有 线 程 都 必 须 在 这 里 等 待 处 理 。 到<br />

__syncthreads() 起<br />

__syncthreads() 被<br />

个<br />

Tesla 架<br />

个 块 内 的 线 程 可 彼 此 协 作 , 一 些 共 享 存 储 器 储 器 访 问 。 更 具 体 地 说 , 可 以 通 过 调 一<br />

用 __syncthreads()<br />

像 L1<br />

内 核 中 指 定 同 步 点 ;<br />

__global__ void matAdd(float A[N][N], float B[N][N],<br />

float C[N][N])<br />

{<br />

int i = blockIdx.x * blockDim.x + threadIdx.x;<br />

int j = blockIdx.y * blockDim.y + threadIdx.y;<br />

if (i < N && j < N)<br />

C[i][j] = A[i][j] + B[i][j];<br />

}<br />

int main()<br />

{<br />

// Kernel invocation<br />

dim3 dimBlock(16, 16);<br />

dim3 dimGrid((N + dimBlock.x – 1) / dimBlock.x,<br />

(N + dimBlock.y – 1) / dimBlock.y);<br />

matAdd(A, B, C);<br />

}<br />

<strong>NVIDIA</strong> 内 核 的 有 限 存 储 器 资 源 限 制 了 每 个 块 的 线 程 数 量 。 在 构 中 , 一 个 线 程 块 最 多 可 以 包 但 一 个 内 核 函 数 能 由 多 个 大 小 相 同 的 线 程 块 执 行 , 因 而 线 程 总 数 应 等 于 每 个 块 的 线 程 数 乘 以 块 的 数 量 。 如 理<br />

blockDim<br />

器<br />

问 此 索 引 。 可 以 通 过 内 置 的 量 在 内 核 中 访 问 线 程 块 的 维 度 。 此 时 , 之 前 的 示 例 代 码 可 修 改 为 : 访 中<br />

的<br />

个<br />

实 现 有 效 的 协 作 , 共 享 存 储 器 被 设 计 为 靠 近 各 处 理 器 内 核 的 低 延 迟 存 储 , 这 很 存 , 设 计 为 轻 量 级 的 , 一 个 块 中 的 所 有 线 程 都 必 须 位 于 同 一 个 处 理 器 内 核 中 。 因 而 , 一 个 处 为<br />

含 512<br />

程 。 线<br />

这 些 块 被 组 织 为 一 个 一 维 或 二 维 线 程 块 网 格<br />

图 2-1<br />

该 网 格 的 维 度 由 。 示<br />

法 的<br />

blockIdx 个 参 数 指 定 。 网 格 内 的 每 个 块 多 可 由 一 个 一 维 或 二 维 索 引 标 识 , 可 通 过 内 置 的 一 第<br />

量 在 内 核<br />

16x16 随 机 选 择 了 大 小 为 们 我<br />

256 块 ( 即 包 含 程 线<br />

线 程 ), 此 外 创 建 了 一 个 网 格 , 它 具 有 足 够 的 块 ,<br />

<strong>CUDA</strong> 编<br />

5<br />

本 2.0


线 程 块 网 格<br />

(local (shared<br />

(constant<br />

(texture<br />

该 memory)。 每 memory),<br />

纹 对 于 同 一 个 应 用 程 序 启 动 的 内 核 而 言 , 全 局 、 常 量 和 纹 理 存 储 器 空 间 都 是 持 久 的 。 和 空 memory)<br />

所<br />

memory) 空<br />

2.2 存 储 器 层 次 结 构<br />

<strong>CUDA</strong><br />

存 储 器 线<br />

图 2-1.<br />

可 在 执 行 过 程 中 访 问 多 个 存 储 器 空 间 的 数 据 , 如 个 线 程 块 都 有 一 个 共 享 存 储 器 程<br />

示 。 每 个 线 程 都 有 一 个 私 有 的 本 地<br />

存 储 器 对 于 块 内 的 所 有 线<br />

间<br />

和 纹 理 存 储 器<br />

间 。 全 局 、 常 量 和 纹 理 存 储 器 空 间 经 过 优 化 , 适 于 不 同 的 存 储 器 用 途 ( 参<br />

图 2-2<br />

(global 是 可 见 的 , 并 且 与 块 具 有 相 同 的 生 命 周 期 。 最 终 , 所 有 线 程 都 可 访 问 同 一 个 全 局 存 储 器<br />

memory)。<br />

此 外 还 有 两 个 只 读 的 存 储 器 空 间 , 可 由 所 有 线 程 访 问 , 这 两 个 空 间 是 常 量 存 储 器 都 程<br />

( 参 见 第 4.3.4)。 滤<br />

见 第 5.1.2.1、5.1.2.3<br />

5.1.2.4)。<br />

理 存 储 器 也 为 某 些 特 殊 的 数 据 格 式 提 供 了 不 同 的 寻 址 模 式 以 及 数 据 过<br />

6 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


所<br />

,<strong>CUDA</strong><br />

(host)<br />

假<br />

memory)。 因 的<br />

之 间 的 数 据 传 输 。 器<br />

(device<br />

,<strong>CUDA</strong> 还<br />

线<br />

章<br />

存<br />

运 分<br />

上<br />

构<br />

上 语<br />

(device)<br />

(host<br />

(<strong>CUDA</strong> runtime) 来 和 memory)<br />

2.3 宿 主 和 设 备<br />

图 2-2.<br />

构 存 储 器 层 次 结 备 存 储 管 理 对 内 核 可 见 的 全 设<br />

外 器 局 、 常 量 和 纹 理 存 储 器 空 间 ( 详 见 此<br />

称 为 宿 主 存 储 器 行 时 )。 这 包 括 设 备 存 储 器 分 配 和 取 消 分 配 , 还 包 括 宿 主 和 设 备 存 储 别<br />

2-3 图 如<br />

设 <strong>CUDA</strong><br />

程 可 在 物 理 上 独 立 的 设 备<br />

语 言 程 序 的 宿 主 示<br />

而 , 一 个 程 序 通 过 调<br />

C , 此 类 设 备 作 为 运 行 行 执<br />

执 行 , 就 是 一 例 。 上<br />

协 处 理 器 存 在 。 比 如 , 内 核<br />

在 GPU<br />

C , 而 行 执<br />

CPU 序 的 其 他 部 分 在 程 言<br />

<strong>CUDA</strong> 编<br />

7<br />

第 4<br />

用 <strong>CUDA</strong><br />

设 宿 主 和 设 备 均 维 护 自 己 的 DRAM, 假<br />

2.0 南 , 版 本 指 程


及 (API)<br />

(software 包 stack)<br />

2-3. 异 图<br />

所<br />

和<br />

(device 应 这<br />

driver)、<br />

2.4 软 件 栈<br />

行 代 码 在 宿 主 上 执 行 , 而 并 行 代 码 在 设 备 上 执 行 。 串<br />

<strong>CUDA</strong> 软<br />

程<br />

: 设 备 驱 动 程 序 示<br />

件 栈<br />

含 多 个 层 , 如<br />

程 序 编 两 个 数 学 库 会 在 其 用<br />

程 异 构 编 8 <strong>CUDA</strong> 编<br />

CUBLAS,<br />

图 2-4<br />

文 档 中 介 绍 。 他<br />

程 接 口<br />

CUFFT 行 时 、 两 个 较 高 级 别 的 通 用 数 学 库 , 即 运 其<br />

2.0 南 , 版 本 指 程


提<br />

(compute 由 capability)<br />

。<br />

程 指 南 , 版<br />

软 件 栈<br />

中<br />

。<br />

。<br />

的<br />

设 备 ( 其<br />

<strong>CUDA</strong> 软<br />

2.5 计 算 能 力<br />

一 个 设 备 的 计 算 能 力<br />

图 2-4.<br />

主 要 修 订 号 和 次 要 修 订 号 定 义<br />

为 1)。 次 要 修 订 号 对 应 于 核 心 架 构 的 增 量 式 改 进 , 可 能 包 含 新 特 性 主<br />

A 录 附<br />

供 了 各 种 计 算 能 力 的 技 术 规 范<br />

A 相 同 主 要 修 订 号 的 设 备 属 于 相 同 的 核 心 架 构 。 附 录 有 具<br />

1.x 的 设 备 均 为 计 算 能 力 是 举 列<br />

<strong>CUDA</strong> 编<br />

9<br />

本 2.0


于<br />

年<br />

编 的<br />

个<br />

月<br />

function unit)、 一<br />

块<br />

块<br />

块<br />

节<br />

。Warp<br />

向 块<br />

,SIMT<br />

统<br />

,Tesla 架<br />

架<br />

(Scalar SP) Processor, 核<br />

向<br />

与<br />

块<br />

块<br />

块<br />

(on-chip)<br />

单<br />

允 宽<br />

,SIMT<br />

线<br />

在<br />

块<br />

个<br />

使<br />

语<br />

(transcendental)<br />

不<br />

(SIMD 而 行<br />

width),<br />

栅<br />

单<br />

,warp<br />

指<br />

块<br />

(cache<br />

第 3 章 GPU 实 现<br />

<strong>NVIDIA</strong><br />

GPU 和<br />

Tesla 架<br />

的 与<br />

计<br />

在 语<br />

GPU(<br />

GTX 280<br />

于 图 形 领 中 再 限 局<br />

核<br />

2006<br />

11<br />

Tesla 的 入 引<br />

图 形 和 计 算 架 构 扩 展 了 GPU, 一<br />

GPU<br />

3.1 具 有 片 上 共 享 存 储 器 的 一 组 SIMT 多 处 理 器<br />

, 其 强 大 的 多 线 程 处 理 器 阵 列 已 经 成 为 高 效 的 统 一 平 台 —— 同 时 适 用 于 图 形 和 通 用 并 行 计 算 应 用 程 序 。 域<br />

件 , 使 这 种 架 构 成 为 最 优 秀 的 超 级 计 算 平 台 。 软<br />

通 过 扩 展 处 理 器 和 存 储 器 的 数 量<br />

GeForce 盖 了 市 场 上 全 线 产 品 , 从 高 性 能 发 烧 级 覆 构<br />

Quadr 业 专<br />

Tesla<br />

GeForce 品 , 一 直 到 多 种 主 流 经 济 型 产 算<br />

A 录 附<br />

可 查 看 所 有<br />

<strong>CUDA</strong> 持 支<br />

GPU<br />

<strong>CUDA</strong> )。 其 计 算 特 性 支 持 利 用 表 列<br />

C<br />

GPU 直 观 地 编 写 中 言<br />

心 程 序 。<br />

Tesla<br />

上 架<br />

程<br />

(Streaming SM) Multiprocessors, 阵<br />

C 有 在 笔 记 本 电 脑 、 台 式 机 、 工 作 站 和 服 务 器 上 的 广 泛 可 用 性 , 配 以 具 构<br />

<strong>CUDA</strong> 程 能 力 和 编 言<br />

的 构 建 以 一 个 可 伸 缩 的 多 线 程 流 式 多 处 理 器 列 为 中 心 。 当 宿 序 调 用 内 核 网 格 时 , 网 格 的 块 将 被 枚 举 并 分 发 到 具 有 可 用 执 行 能 力 的 多 处 理 器 上 。 构<br />

8<br />

(special<br />

器 包 含 功 能 单 元 理 处 多<br />

标 量 处 理 器<br />

、 两 个 用 于 超 越 函 数 特 殊 个 多 线 程 指 令 单 元 以 及 片 上 享 存 储 器 。 多 处 理 器 会 在 硬 心<br />

个 线 程 块 的 线 程 在 一 个 多 处 理 器 上 并 发 执 行 。 在 线 程 块 终 止 时 , 将 在 空 闲 多 处 理 器 上 启 动 新 块 。 的 一<br />

<strong>CUDA</strong> 章 介 绍 一 这<br />

Tesla 型 与 模 程<br />

的 对 应 关 系 。 构<br />

共<br />

multiple-thread, 单<br />

warp 块<br />

步 。 快 速 的 栅 障 同 步 与 轻 量 级 线 程 创 建 和 零 开 销 的 线 程 调 度 相 结 合 , 有 效 地 为 细 粒 度 并 行 化 提 供 了 支 持 , 举 例 来 说 , 您 可 以 为 各 数 据 元 素 ( 如 图 像 中 的 一 个 像 素 、 语 音 中 的 一 个 语 音 元 素 、 基 于 网 格 的 计 算 中 的 一 同<br />

主 CPU<br />

的 <strong>CUDA</strong><br />

个 单 元 ) 分 配 一 个 线 程 , 从 而 对 问 题 进 行 细 粒 度 分 解 。<br />

令 、 多 线 程 ) 的 新 架 构 。 多 处 理 器 会 将 各 线 程 映 射 到 一 个 标 量 处 理 器 核 心 , 各 标 量 线 半 指<br />

可 随 意 分 支 、 独 立 执 行 。 都 包 含 连 续 的 线 程 , 递 增 线 也<br />

包 含 线 程 0。 中<br />

中 的 线 程 索 引 之 间 的 关 系 。 块<br />

次 准 备 发 出 一 条 指 令 时 的 活 动 线 程 每<br />

并 将 待 发 出 的 指 令 发 送 到 该 的 全 线 程 均 有 明 确 的 执 行 ,<br />

中 创 建 、 管 理 和 执 行 并 发 线 程 , 而 调 度 开 销 保 持 为 0。 它 可 通 过 一 条 内 部 指 令 实 件<br />

现 __syncthreads()<br />

障<br />

warp 块<br />

块 单<br />

块<br />

块 块<br />

个<br />

块<br />

SIMT(single-instruction, 管 理 运 行 各 种 不 同 程 序 的 数 百 个 线 程 , 多 处 理 器 利 用 了 一 种 称 为 了 为<br />

路 径 时 , 可 达 到 最 高 效 率 。 如 果 一<br />

的 线 程 通 过 独 立 于 数 据 的 条 件 分 支 而 分 散<br />

将 连 续<br />

第<br />

warp 调 度 和 执 行 线 程 , 这 样 的 线 程 组 称 为 、 理<br />

此 术 语 源 于 第 一 种 并 行 线 程 技 术 weaving。 。(<br />

warp<br />

程 使 用 自 己 的 指 令 地 址 和 寄 存 器 状 态 独 立 执 行 。 多 处 理 器 SIMT<br />

32 以 元<br />

并 行 线 程 为 一 组 来 创 建 、 管<br />

warp 是 一 个 以 可<br />

SIMT 一 半 或 第 二 半 。) 构 成 第 的<br />

的 各 个 线 程 在 同 一 个 程 序 地 址 一 起 启 动 , 但<br />

执 行 所 使 用 的 各 分 支 路 径 , 而 禁 用 未 在 此 路 径 上 的 线 程 , 完 成 所 有 路 径 时 , 线 程 重 新 汇 聚 到 同 一 执 行 路 径<br />

warp 个 多 处 理 器 指 定 了 一 个 或 多 个 要 执 行 的 线 程 块 时 , 它 会 将 其 分 成 一 为<br />

SIMT 由 并 ,<br />

元 进 行 调 度 。<br />

10 <strong>CUDA</strong> 编<br />

warp 分 割 为 块 将<br />

warp 法 总 是 相 同 的 , 每 个 方 的<br />

程 ID,<br />

warp 个 一<br />

SIMT 架<br />

第 2.1<br />

ID 了 线 程 绍 介<br />

warp 会 选 择 一 个 可 待 使 用 的 都 元<br />

warp 执 行 一 条 通 用 指 令 , 因 此 在 次 每<br />

部 32<br />

线<br />

个 warp<br />

彼 此 无 关 的 代 码 路 径 。 单 是<br />

warp 分 支 仅 在 。 下<br />

warp 现 , 不 同 的 出 内<br />

总 是 独 立 执 行 的 —— 无 论 它 们 执 行 的 是 通 用 的 代 码 路 径 还<br />

类 似 于 SIMD( 构<br />

指 令 、 多 数 据 ) 向 量 组 织 方 法 , 共 同 之 处 是 使 用 单 指 令 来 控 制 多 个 处 理 元 素 。<br />

warp 个 一 少<br />

cache 线 程 分 支 , 即 可 实 现 显 著 的 性 能 提 升 。 在 实 践 中 , 这 与 传 统 代 码 中 的 的 内<br />

2.0 南 , 版 本 指 程<br />

SIMD 主 要 差 别 在 于 项 一<br />

SIMD 织 方 法 会 向 软 件 公 开 组 量<br />

度<br />

SIMT<br />

令 指 定 单<br />

SIMT , 还 允 许 为 协 同 线 程 编 写 数 据 并 行 代 码 。 为 了 确 保 正 确 性 , 程 序 员 可 忽 略 码 代<br />

为 , 但 通 过 尽 量 减<br />

作 计 , 在 代 码 结 构 中 就 必 须 考 虑 其 大 小 。 另 一 方 面 , 向 量 架 构 要 求 软 件 操 作 存 储 器 合 并 , 并 手 动 管 理 分 支 。<br />

line)<br />

SIMD 程 的 执 行 和 分 支 行 为 。 与 线 一<br />

量 机 不 同<br />

许 程 序 员 为 独 立 、 标 量 线 程 编 写 线 程 级 的 并 行<br />

cache 似 : 在 以 正 确 性 为 目 标 进 行 设 计 时 , 可 忽 略 相 用<br />

的 大 小 , 但 如 果 以 峰 值 性 能 为 目 标 进 行 设


所<br />

块<br />

位<br />

(constant<br />

(texture<br />

(texture<br />

cache), 由<br />

cache), 由<br />

写 访 unit)<br />

程 指 南 , 版<br />

块<br />

一 项 读 取 、 修 改 或 写 入 操 作 都 将 发 生 , 且 均 为 串 行 化 操 作 , 但 这 些 操 作 所 发 生 的 顺 序 无 法 确 定 。 块<br />

多<br />

硬<br />

节<br />

个<br />

<br />

<br />

<br />

并 每<br />

行 数 据 缓 存 或 共 享 存 储 器 , 由 所 有 标 量 处 理 器 核 心 共 享 , 共 享 存 储 器 空 间 就 位 于 此 处<br />

<br />

3-1 图 如<br />

个 只 读 纹 理 缓 所 有 标 量 处 理 器 核 心 共 享 , 加 速 从 纹 理 存 储 器 空 间 进 行 的 读 取 操 作 ( 这 是 设 备 存 储 器 的 一 个 只 读 区 域 ), 每 个 多 处 理 器 都 会 通 过 实 现 不 同 寻 址 模 型 和 数 据 过 滤 的 纹 一<br />

作 ( 这 是 设 备 存 储 器 的 一 个 只 读 区 域 );<br />

32 理 器 上 有 一 组 本 地 处 个<br />

存 器 ; 寄<br />

, 每 个 多 处 理 器 都 有 一 个 属 于 以 下 四 种 类 型 之 一 的 片 上 存 储 器 : ; 只 读 常 量 缓 存 所 有 标 量 处 理 器 核 心 共 享 , 可 加 速 从 常 量 存 储 器 空 间 进 行 的 读 取 操 示<br />

个 多 处 理 器 一 次 可 处 理 的 块 数 量 取 决 于 给 定 的 内 核 中 , 每 个 线 程 需 要 多 少 个 寄 存 器 、 每 个 块 需 要 多 少 共 享 存 储 器 , 这 是 因 为 多 处 理 器 的 寄 存 器 和 共 享 存 储 器 被 分 配 给 一 批 块 的 所 有 线 程 。 如 果 没 有 足 够 的 寄 存 器 线 程 块 。 一<br />

理 单 元<br />

4.3.4 理 缓 存 , 相 关 内 容 请 参 见 第 纹 问<br />

。<br />

8 享 存 储 器 可 供 多 处 理 器 用 于 处 理 至 少 一 个 块 , 内 核 会 无 法 启 动 。 一 个 多 处 理 器 可 并 发 执 行 最 多 共 或<br />

/ 和 全 局 存 储 器 空 间 是 设 备 存 储 器 的 读 区 域 , 无 缓 存 。 地 本<br />

warp 行 原 子 指 令 来 为 执 块<br />

的 多 个 线 程 读 取 、 修 改 和 写 入 全 局 存 储 器 中 的 同 一 位 置 , 则 针 对 该 位 置 的 每<br />

warp 果 如<br />

warp 的 非 原 子 指 令 为 行 执<br />

的 多 个 线 程 写 入 全 局 或 共 享 存 储 器 中 的 同 一 位 置 , 针 对 此 位 置<br />

warp 行 化 写 入 操 作 的 数 量 和 这 些 写 入 操 作 所 发 生 的 顺 序 将 无 法 确 定 , 但 其 中 一 项 操 作 必 将 成 功 。 如 果 串 的<br />

具 有 片 上 共 享 存 储 器 的 一<br />

理 器 处<br />

<strong>CUDA</strong> 编<br />

11<br />

硬 件 模 型<br />

本 2.0<br />

组 SIMT<br />

图 3-1.


模<br />

系<br />

位<br />

键<br />

而 导 致 此 类 应 用 程 序 崩 溃 。 从<br />

模<br />

能<br />

应<br />

作<br />

可 视 设<br />

设<br />

(primary 它 控 的<br />

surface),<br />

键<br />

上 应 MB。(<br />

应<br />

必<br />

的<br />

都<br />

3.2 多 个 设 备<br />

备 , 因 为 所<br />

须 具 有 相<br />

3.3 模 式 切 换<br />

SLI 类 型 。 但 如 果 系 统 采 用 的 是 内 关 式 。 的 同<br />

, 则 仅 有 一 够 将 式<br />

GPU 在 多 要 若<br />

GPU 运 行 , 且 应 用 程 序 将 多 个 上 统<br />

GPU 将<br />

存<br />

储 器 专 门 用 于 处 理 所 谓 的 主 表 面<br />

为 <strong>CUDA</strong><br />

GPU 用 , 则 这 些 使 备<br />

用 于 刷 新 用 户 所 见 的 显 示 设<br />

个 GPU<br />

<strong>CUDA</strong> 作 用<br />

MB 的<br />

控 制 面 板 将<br />

示 控 制 面 板 ) 发 显<br />

有 GPU<br />

<strong>CUDA</strong> 动 程 序 栈 的 最 低 级 别 融 合 。 要 使 驱 在<br />

各 GPU<br />

<strong>CUDA</strong> 立 设 备 , 需 要 在 独 为<br />

闭 SLI<br />

DRAM 分 部<br />

<strong>NVIDIA</strong> 当 用 户 通 过 更 改 显 示 器 的 分 辨 率 或 位 深 度 ( 使 用 。 备<br />

Windows 板 或 面 制<br />

1280x1024x32 式 切 换 时 , 主 表 面 所 需 的 存 储 器 数 量 会 随 之 改 变 。 例 如 , 如 果 用 户 将 显 示 器 的 分 辨 率 从 模 起<br />

1600x1200x32 改 为 更 位<br />

7.68 统 必 须 为 主 表 面 分 配 系 ,<br />

5.24 器 , 而 不 是 储 存<br />

使 用 防 锯 齿<br />

Windows 运 行 的 全 屏 图 形 应 用 程 序 可 能 需 要 为 主 表 面 分 配 更 多 显 示 存 储 器 。) 在 置 设<br />

, 其 他 事 件 也 可 能<br />

<strong>CUDA</strong> 模 式 切 换 增 加 了 主 表 面 所 需 的 存 储 器 数 量 , 系 统 可 能 就 必 须 挪 用 分 配 给 果 如<br />

用 程 序 的 存 储 器 ,<br />

会 启 动 显 示 模 式 切 换 , 包 括 启 动 全 屏 DirectX<br />

Alt+Tab 序 、 按 程 用<br />

DirectX 屏 全 从<br />

用 程 序 中 切 换<br />

Ctrl+Alt+Del 或 者 按 来 出<br />

定 计 算 机 。 锁<br />

12 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


编<br />

的<br />

,C 标<br />

限<br />

(host)<br />

(function<br />

(variable qualifier), type<br />

编 指<br />

。<br />

进<br />

,4.2.5 节<br />

节<br />

,nvcc 发 出 错 误 或 警 报 将<br />

第 4 章 应 用 程 序 编 程 接 口<br />

4.1 C 编 程 语 言 的 扩 展<br />

<strong>CUDA</strong> 编<br />

编<br />

序 。 它 包 含 : 节 程<br />

运 行 时 库 , 可 分 割 为 : 个<br />

C<br />

<br />

<br />

一 语<br />

节<br />

<br />

<br />

一<br />

组<br />

节 标<br />

C 口 的 目 标 是 为 熟 悉 接 程<br />

程 语 言 的 用 户 提 供 相 对 简 单 的 途 径 , 使 之 可 轻 松 编 写 由 设 备 执 行 的<br />

4.2 最 小 扩 展 集 , 如 的 言<br />

述 , 这 允 许 程 序 员 使 源 代 码 的 某 些 部 分 可 在 设 备 上 执 行 ; 所<br />

有 必 要 强 调<br />

库 中 支 持 在 设 备 上 运 行 的 函 数 只 有 通 用 运 行 时 组 件 所 提 供 的 函 数 。 准<br />

4.2 语 言 扩 展<br />

。 集 子 此 持 支 将<br />

语 言 扩 展<br />

个 计 算 设 备 ; 多<br />

一 个 宿 主<br />

4.5 如 , 件<br />

所 述 , 运 行 在 宿 主 上 , 提 供 函 数 来 通 过 宿 主 控 制 和 访 问 一 个 或<br />

4.4 备 组 件 , 如 设 个<br />

述 , 运 行 在 设 备 上 , 提 供 特 定 于 设 备 的 函 数 ; 所<br />

<br />

qualifier), type<br />

节 指<br />

4.3 通 用 组 件 , 如 个 一<br />

C , 提 供 内 置 向 量 类 型 和 述 所<br />

准 库 的 一 个 子 集 , 宿 主 和 设 备 代 码 都<br />

4.2.1<br />

类 型 限 定 符 宿 主 还 是 可 通 过 设 备 调 用 ( 参 见 第 数 函<br />

函 数 是 在 宿 主 上 还 是 设 备 上 执 行 , 以 及 函 数 是 可 通 过 ); 定<br />

语 言 的 扩 展 共 有 四 重 : 程<br />

<br />

<br />

四 一 变<br />

节 节<br />

条 新 指 令 , 指 定 如 何 通 过 宿 主 在 设 备 上 执 行 内 核 ( 参 见<br />

对 C<br />

);<br />

)。<br />

);<br />

量 类 型 限 定 符<br />

4.2.2 个 变 量 在 设 备 上 的 存 储 器 位 置 ( 参 见 第 一 定<br />

简 单 介 绍 了 相 关 内 容 。 关<br />

4.2.3<br />

编 介 将 其 文 中 供 第<br />

4.2.1 函 数 类 型 限 定 符<br />

一 些 限 制 , 下 面 几 个 小 节 将 分 别 加 以 介 绍 。 如 果 违 背 了 这 些 限 制 信 息 , 但 有 些 违 规 情 况 无 法 检 测 到 。 有 具 均 展 扩 些 。 提 档 他 在 绍 体 译 行 这<br />

函 数 类 型 限 定 符<br />

4.2.4 置 变 量 , 指 定 网 格 和 块 维 度 以 及 块 和 线 程 索 引 ( 参 见 第 内 个<br />

<strong>CUDA</strong> 这 些 扩 展 的 所 有 源 文 件 都 必 须 使 用 含 包<br />

nvcc 器 译<br />

4.2.1.1 __device__<br />

于 nvcc<br />

<br />

仅 在<br />

<strong>CUDA</strong><br />

设 备 上 执 行 ; 可 通 过 设 备 调 用<br />

编<br />

定 符 声 明 的 函 数 具 有 以 下 特 征 :<br />

13<br />

__device__ 用 使<br />

2.0 南 , 版 本 指 程


限<br />

限<br />

限<br />

限<br />

和<br />

限<br />

(void)。<br />

:<br />

限 定 符 声 明 函 数 , 。 或<br />

variable)。<br />

(static<br />

字<br />

。<br />

限<br />

。<br />

4.2.1.2 __global__<br />

<br />

仅 在<br />

定 符 可 将 函 数 声 明 为 内 核 。 此 类 函 数<br />

4.2.1.3 __host__<br />

。<br />

<br />

仅 在<br />

备 上 执 行 ; 可 通 过 宿 主 调 用 设<br />

主 上 执 行 ; 宿<br />

__global__ 用 使<br />

通 过 宿 主 调 用 。 定 符 声 明 函 数 等 同 于 不 使 可<br />

4.2.1.4 限 制<br />

__host__ 用 使<br />

符 声 明 的 函 数 具 有 以 下 特 征 : 定<br />

使<br />

__device__<br />

仅<br />

和 __device__<br />

__device__<br />

__device__<br />

__global__<br />

__global__ 函 和 函 限<br />

。 函<br />

节<br />

用 __host__<br />

用 __host__、__device__<br />

__global__<br />

这 两 种 情 况 下 , 函 数 都 将 仅 为 宿 主 进 行 编 译 。<br />

但 __host__<br />

定 符 一 起 使 用 , 此 时 函 数 将 为 宿 主 和 设 备 进 行 编 译<br />

__device__ 也 可 与 符 定<br />

不 支 持 递 归 。<br />

函 体 内 无 法 声 明 静 态 变 量 数 的 参 数 不 得 为 变 量 。<br />

__global__<br />

__global__ 函 函<br />

__global__ 函<br />

__global__<br />

__global__<br />

符 无 法 一 起 使 用<br />

4.2.2 变 量 类 型 限 定 符<br />

变 量 类 型 限 定 符<br />

__global__ 地 址 无 法 获 取 , 但 支 持 的 数<br />

__host__<br />

的 函 数 指 针 。 介 绍 的 方 法 指 定 其 执 行 配 置 数<br />

4.2.2.1 __device__<br />

数 的 返 回 类 型 必 须 为 空<br />

的 调 用 是 异 步 的 , 也 就 是 说 它 会 在 设 备 执 行 完 成 之 前 返 回<br />

__device__<br />

数<br />

限<br />

<br />

<br />

可 与 位<br />

符 声 明 位 于 设 备 上 的 变 量 。 体 地 指 定 变 量 属 于 哪 个 存 储 器 空 间 。 如 果 未 出 现 其 他 任 何 限 定 符 , 则 变 量 具 有 以 下 特 征 : 定<br />

全 局 存 储 器 空 间 中 ; 应 用 程 序 具 有 相 同 的 生 命 周 期 ; 于<br />

对 __global__<br />

4.2.3 任 何 调 用 都 必 须 按 第 的 数<br />

定 符 一 起 使 用 , 以 更 具<br />

256 数 将 同 时 通 过 共 享 存 储 器 传 递 给 设 备 , 且 限 制 为 参 数<br />

。 节<br />

4.2.2.2 __constant__<br />

__constant__ 限<br />

限<br />

<br />

与 位<br />

过 网 格 内 的 所 有 线 程 访 问 , 也 可 通 过 运 行 时 库 从 宿 主 访 问 。 通<br />

常 量 存 储 器 空 间 中 ; 应 用 程 序 具 有 相 同 的 生 命 周 期 ; 于<br />

14 <strong>CUDA</strong> 编<br />

__device__ 下 来 的 三 节 中 介 绍 的 其 他 类 型 限 定 符 中 , 最 多 只 能 有 一 种 可 与 接 在<br />

__device__ 可 选 择 与 符 定<br />

符 一 起 使 用 , 所 声 明 的 变 量 具 有 以 下 特 征 : 定<br />

2.0 南 , 版 本 指 程


节<br />

变<br />

和<br />

助<br />

变<br />

(implied<br />

(segmentation 和 fault)<br />

助<br />

节<br />

可<br />

4.2.2.3 __shared__<br />

__shared__ 限<br />

<br />

<br />

尽 与 位<br />

过 网 格 内 的 所 有 线 程 访 问 , 也 可 通 过 运 行 时 库 从 宿 主 访 问 。 通<br />

于 线 程 块 的 共 享 存 储 器 空 间 中 ; 限<br />

具 有 相 同 的 生 命 周 期 ; 节 块<br />

extern __shared__ float shared[];<br />

节<br />

short array0[128];<br />

float array1[64];<br />

int array2[256];<br />

通 过 块 内 的 所 有 线 程 访 问 。 参 将 共 享 存 储 器 声 明 为 外 部 数 组 时 , 例 如 : 可<br />

, 因 此 数 组 中 的 变 量 布 局 必 须 通 过 偏 移 显 式 管 理 。 例 如 , 如 果 一 名 用 户 希 望 在 动 态 分 配 的 共 享 存 储 器 内 始<br />

__device__ 可 选 择 与 符 定<br />

符 一 起 使 用 , 所 声 明 的 变 量 具 有 以 下 特 征 : 定<br />

extern __shared__ char array[];<br />

__device__ void func() // __device__ or __global__ function<br />

{<br />

short* array0 = (short*)array;<br />

float* array1 = (float*)&array0[128];<br />

int* array2 = (int*)&array1[64];<br />

}<br />

得 与 以 下 代 码 对 应 的 内 容 : 则 应 通 过 以 下 方 法 声 明 和 初 始 化 数 组 : 获<br />

有 在 __syncthreads()( 只<br />

4.4.2 第 见<br />

) 的 执 行 写 入 之 后 , 才 能 保 证 共 享 变 量 对 其 他 线 程 可 见 。 除 非 变<br />

volatile 声 明 为 被 量<br />

, 否 则 只 要 之 前 的 语 句 完 成 , 编 译 器 即 可 随 意 优 化 共 享 存 储 器 的 读 写 操 作 。 量<br />

4.2.3 的 大 小 将 在 启 动 时 确 定 ( 参 见 第 组 数<br />

)。 所 有 变 量 均 以 这 种 形 式 声 明 , 在 存 储 器 中 的 同 一 地 址 开<br />

4.2.2.4 限 制<br />

和<br />

成<br />

__shared__ 和<br />

变<br />

static storage)。<br />

__constant__<br />

量 无 法 使<br />

字 定 义 为 外 部 变 量 。 键<br />

__device__、__shared__ 和<br />

变<br />

关<br />

__device__ 和<br />

变<br />

struct 限 定 符 不 允 许 被 用 于 在 宿 主 上 执 行 的 函 数 内 的 些 这<br />

union<br />

的 形 参 和 局 部 变 量 。 员<br />

_shared_ 变<br />

量 的 声 明 中 不 可 包 含 初 始 化<br />

和<br />

)。<br />

__constant__<br />

量 具 有 隐 含 的 静 态 存 储<br />

设 备 代 码 中 声 明 、 不 带 任 何 限 定 符 的 自 动 变 量 通 常 位 于 寄 存 器 中 。 但 在 某 些 情 况 下 , 编 译 器 可 能 择 将 其 置 于 本 地 存 储 器 中 。 如 果 使 用 占 用 了 过 多 寄 存 器 空 间 的 大 型 结 构 或 数 组 , 或 者 编 译 器 无 法 确 定 其 是 否 使 汇 或 选 在<br />

options =-v<br />

。<br />

选<br />

用 extern<br />

__constant__<br />

仅 允 许 在 文 件 作 用 域 内 使 用 。 量<br />

<strong>CUDA</strong> 编<br />

针 即 受 支 持 , 否 则 将 仅 限 于 指 向 在 全 局 存 储 器 空 间 中 分 配 或 声 明 的 存 储 器 。<br />

15<br />

__constant__ 为 设 备 或 从 设 备 指 派 可 不<br />

4.5.2.3 仅 可 通 过 宿 主 运 行 时 函 数 从 宿 主 指 派 ( 参 见 第 , 量<br />

第 4.5.3.6<br />

--ptxas- 寄 存 器 空 间 。 可 通 过 使 用 多 过<br />

项 编 译 来 进 行 检 查 , 这 将 报 告 本 地 存 储 器 的 使 用 情 况<br />

ptx 定 数 量 索 引 的 数 组 , 则 往 往 会 出 现 这 种 情 况 。 检 查 固 用<br />

–ptx 码 ( 通 过 使 用 代 编<br />

–keep<br />

项 编<br />

用 , 将 导 致 不 确 定 的 行 为 , 往 往 会 出 现 分 区 错 误<br />

用 程 序 终 止 。 应<br />

.local 得 ) 即 可 在 初 次 编 译 过 程 中 确 定 一 个 变 量 是 否 位 于 本 地 存 储 器 中 , 因 为 它 将 使 用 获 译<br />

记 符 声 明 ,<br />

如 果 取 消 在 宿 主 上 执 行 的 代 码 中 全 局 或 共 享 存 储 器 指 针 , 或 者 在 设 备 上 执 行 的 代 码 中 宿 主 存 储 器 指 针 的 引<br />

只 要 编 译 器 能 够 确 定 在 设 备 上 执 行 的 代 码 中 的 指 针 指 向 的 是 共 享 存 储 器 空 间 还 是 全 局 存 储 器 空 间 , 此 类 指<br />

(lmem)。<br />

ld.local 用 使 可<br />

st.local<br />

记 符 访 问 。 如 果 不 是 这 样 , 在 后 续 编 译 阶 段 仍 能 确 定 是 否 占 用 了 目 标 架 构 的<br />

2.0 南 , 版 本 指 程


函<br />

或<br />

节<br />

节<br />

节<br />

节<br />

节 变<br />

;S<br />

变 或<br />

configuration)。<br />

(execution<br />

或<br />

,Dg.x<br />

,Db.x<br />

节<br />

是<br />

(<br />

4.2.3 执 行 配 置<br />

主 代 码 中 使 用 。 宿<br />

取 __device__、__shared__<br />

通 过 获<br />

__constant__<br />

量 的 地 址 而 获 得 的 地 址 仅 可 在 设 备 代 码 中 使 用 。 通<br />

Dg<br />

Dg.z<br />

Db 的 无 节<br />

节<br />

Db, Ns, s>>> 形<br />

* Dg.y 等<br />

* Db.y * Db.z 等<br />

量 的 地 址 仅 可 在<br />

过 cudaGetSymbolAddress()<br />

4.5.23 第 见 参<br />

__device__ 取 的 获 )<br />

__constant__<br />

对 __global__<br />

<br />

Ns 的<br />

4.5.1.5 配 置 定 义 将 用 于 在 该 设 备 上 执 行 函 数 的 网 格 和 块 的 维 度 , 以 及 相 关 的 流 ( 有 关 流 的 内 容 将 在 第 行 执<br />


工<br />

代<br />

语<br />

,__device__ 函<br />

对<br />

块<br />

驱<br />

源<br />

小 。 大<br />

代<br />

在<br />

所<br />

(inlined)。__noinline__ 函<br />

(trip<br />

。#pragma<br />

语<br />

限<br />

节 对<br />

对<br />

4.2.4.5 warpSize<br />

4.2.4.6 限 制<br />

<br />

不 4.2.5 使 用 NVCC 进 行 编 译<br />

包 试 图 获 取 任 何 内 置 变 量 的 地 址 。 允 许 为 任 何 内 置 变 量 赋 值 。<br />

变 量 的 类 型 为 int, 此<br />

warp 线 程 为 单 位 的 以 含<br />

nvcc 是<br />

nvcc 的<br />

<strong>CUDA</strong> 可 简 化 种 一<br />

编 译 过 程 的 编 译 器 驱 动 程 序 : 它 提 供 了 简 单 、 熟 悉 的 命 令 行 选 项 , 通 过 调 用 实 现 不 同 编 译 阶 段 的 工 具 集 合 来 执 行 它 们 。 基 本 工 作 流 在 于 将 设 备 代 码 与 宿 主 代 码 分 离 开 来 , 并 将 设 备 代 码 编 译 为 二 进 制 形 式 象 。 码<br />

或 cubin<br />

4.5.2 节<br />

运<br />

的<br />

子<br />

特<br />

语<br />

C 成 的 宿 主 代 码 将 作 为 需 要 使 用 其 他 工 具 编 译 的 生 所<br />

码 输 出 , 或 通 过 在 最 后 一 个 编 译 阶 段 中 调 用 宿 主<br />

译 器 直 接 作 为 对 象 代 码 输 出 。 编<br />

)。<br />

<strong>CUDA</strong> 程 序 可 忽 略 所 生 成 的 宿 主 代 码 , 使 用 用 应<br />

API 序 程 动<br />

cubin 上 加 载 并 执 行 备 设<br />

象 , 也 可 链<br />

cubin 所 生 成 的 宿 主 代 码 , 其 中 包 含 到 接<br />

4.2.3 其 形 式 为 全 局 初 始 化 数 据 数 组 , 包 含 将 第 , 象<br />

所 述 执<br />

<strong>CUDA</strong> 置 语 法 转 换 为 必 要 的 配 行<br />

启 动 代 码 的 转 换 , 目 的 在 于 加 载 和 启 动 编 译 后 的 各 内 核 ( 参 见 第 行<br />

C++ 器 的 前 端 根 据 译 编<br />

<strong>CUDA</strong> 则 处 理 规 法<br />

C++ 。 宿 主 代 码 支 持 完 整 的 件 文<br />

法 。 但 设 备 代 码 仅 支<br />

nvcc 引<br />

4.2.5.1 __noinline__<br />

认 情 况 下 数 总 是 内 联 要 内 联 该 函 数 。 函 数 体 必 须 位 于 所 调 用 的 同 一 个 文 件 内 。 默<br />

数 限 定 符 可 用 于 指 示 编 译 器 尽 可 能 不<br />

持 C++<br />

C<br />

C++ 类 、 继 承 、 基 本 块 内 的 变 量 声 明 等 , 集<br />

C++ 性 不 受 支 持 。 由 于 使 用 了 特 殊<br />

法<br />

了 两 个 编 译 器 指 令 , 下 面 几 节 将 加 以 介 绍 。 入<br />

malloc() , 因 此 若 未 经 过 强 制 类 型 转 换 , 无 法 将 空 指 针 ( 例 如 则 规<br />

回 的 空 指 针 ) 指 派 给 非 空 指 针 。 返<br />

符 。 定<br />

nvcc 于 关<br />

流 和 命 令 选 项 的 详 细 说 明 将 在 其 他 文 档 中 提 供 。 作<br />

4.2.5.2 #pragma unroll<br />

认 情 况 下 , 编 译 器 将 展 开 具 有 已 知 行 程 计 数 小 循 环 令 可 用 于 控 制 任 何 给 定 循 环 的 展 开 操 作 。 它 必 须 紧 接 于 循 环 之 前 , 而 且 仅 应 用 于 该 循 环 。 可 选 择 在 其 后 接 一 个 数 字 , 指 定 默<br />

count) 的<br />

unroll 指<br />

#pragma unroll 5<br />

for (int i = 0; i < n; ++i)<br />

次<br />

小<br />

<strong>CUDA</strong> 编<br />

17<br />

__noinline__ 函 数 具 有 指 针 参 数 或 者 具 有 较 大 的 参 数 列 表 , 则 编 译 器 不 会 遵 从 果 如<br />

#pragma unroll 1 将<br />

unroll 后<br />

须 展 开 多 少 次 循 环 。 例 如 , 在 下 面 的 代 码 示 例 中 : 必<br />

则 程 序 的 正 确 性 将 受 到 影 响 )。 阻 止 编 译 器 展 开 一 个 循 环 。<br />

5,<br />

5 将 展 开 环 循<br />

n 序 员 需 要 负 责 确 保 展 开 操 作 不 会 影 响 程 序 的 正 确 性 ( 在 上 面 的 示 例 中 , 如 果 程 。<br />

于<br />

2.0 南 , 版 本 指 程<br />

#pragma 在 果 如<br />

未 指 定 任 何 数 据 , 如 果 其 行 程 计 数 为 常 数 , 则 该 循 环 将 完 全 展 开 , 否 则 将 不 会 展


的<br />

y)。<br />

的<br />

4.3 通 用 运 行 时 组 件<br />

4.3.1 内 置 向 量 类 型<br />

。 开<br />

4.3.1.1 char1、uchar1、char2、uchar2、char3、uchar3、char4、uchar4、<br />

short1、ushort1、short2、ushort2、short3、ushort3、short4、ushort4、<br />

int1、uint1、int2、uint2、int3、uint3、int4、uint4、long1、ulong1、long2、<br />

主 和 设 备 函 数 均 可 使 用 通 用 运 行 时 组 件 。 宿<br />

ulong2、long3、ulong3、long4、ulong4、float1、float2、float3、float4、<br />

double2<br />

y、z 和<br />

访<br />

int2 make_int2(int x, int y);<br />

name> 的<br />

个<br />

4.3.1.2 dim3 类 型<br />

1、2、3、4 向 量 类 型 继 承 自 基 本 整 形 和 浮 点 类 型 。 它 们 均 为 结 构 体 , 第 些 这<br />

量 分 别 可 通 过 字 段 x、 分<br />

w<br />

make_


、2 分<br />

位 是 的<br />

节<br />

(texture<br />

(texture reference) 的 的 fetch)<br />

“texture 纹 elements(<br />

类<br />

且<br />

。<br />

;Type 仅<br />

。<br />

或<br />

和<br />

位<br />

1.0], 有<br />

节<br />

和<br />

节<br />

(texture 将 coordinate)<br />

节<br />

1.0], 例<br />

和<br />

和<br />

,1.25<br />

“wrap”<br />

的<br />

寻 或<br />

。Wrap<br />

的<br />

的<br />

间<br />

节<br />

第<br />

的 围<br />

。 对 于<br />

4.3.4 纹 理 类 型<br />

<strong>CUDA</strong> 支<br />

用<br />

数 据 可 带 来 多 方 面 的 性 能 收 益 , 请 参 见 第 5.4<br />

个 参 数 指 定 称 为 纹 理 参 考<br />

对 象<br />

持 GPU<br />

于 图 形 的 纹 理 硬 件 子 集 , 使 之 可 访 问 纹 理 存 储 器 。 从 纹 理 存 储 器 而 非 全 局 存 储 器 读 取<br />

4.3.4.1 纹 理 参 考 声 明<br />

绑 定 到 存 储 器 的 某 些 区 域 ( 即 纹 理 ), 之 后 才 能 供 内 核 。 多 不 同 的 纹 理 参 考 可 绑 定 到 同 一 个 , 也 可 绑 定 到 在 存 储 器 中 存 在 重 叠 的 纹 理 。 纹 理 参 考 有 一 些 属 性 。 其 中 之 一 就 是 其 维 度 , 指 定 纹 理 是 使 用 一 个 纹 理 坐 标 纹 理 作 为 一 维 数 组 寻 址 、 使 用 两 个 纹 理 坐 标 作 为 二 维 数 组 寻 址 , 还 是 使 用 三 个 纹 理 坐 标 作 为 三 维 数 组 寻 址 。 数 组 其<br />

即<br />

内 核 使 用 称 为 纹 理 拾 取<br />

4.4.3 函 数 读 取 纹 理 存 储 器 , 请 参 见 第 备 设<br />

。 纹 理 拾 取 的 第 一<br />

4.5.2.6 参 考 定 义 拾 取 哪 部 分 的 纹 理 存 储 器 。 必 须 通 过 宿 主 运 行 时 函 数 ( 参 见 第 理 纹<br />

第 4.5.3.9<br />

) 将<br />

他 属 性 定 义 纹 理 拾 取 的 输 入 和 输 出 数 据 类 型 , 并 指 定 如 何 介 绍 输 入 坐 标 、 应 进 行 怎 样 的 处 理 。 其<br />

texture texRef;<br />

<br />

Type 指<br />

元 素 称 为 texel, 的<br />

元 素 )” 的 简 写 。 理<br />

1 的 义<br />

量<br />

量 和 4<br />

向 量 类 型 ; 量<br />

Dim<br />

ReadMode 等 指 分<br />

分<br />

或<br />

是<br />

为<br />

位<br />

理 参 考 的 部 分 属 性 是 不 变 的 , 在 编 译 时 必 须 为 已 知 , 这 些 属 性 是 在 声 明 纹 理 参 考 时 指 定 的 。 纹 理 参 考 在 其 中 : 纹<br />

texture 作 用 域 内 声 明 , 形 式 为 件 文<br />

的 变 量 : 型<br />

定 拾 取 纹 理 时 所 返 回 的 数 据 类 型<br />

4.3.1.1 基 本 整 型 、 单 精 度 浮 点 类 型 和 第 于 限<br />

定<br />

转 换 操 作 ;ReadMode<br />

如<br />

4.3.4.2 运 行 时 纹 理 参 考 属 性<br />

1、2 理 参 考 的 维 度 , 其 值 为 纹 定<br />

3;Dim<br />

个 可 选 的 参 数 , 默 认 值 为 1; 一<br />

于 cudaReadModeNormalizedFloat<br />

cudaReadModeElementType;<br />

果 是<br />

cudaReadModeNormalizedFloat,<br />

Type<br />

16<br />

或 8<br />

整 型 类 型 , 则 值 将 作 为 浮 点 类 型 返 回 , 对<br />

则<br />

于 所 有 整 型 数 据 而 言 , 无 符 号 整 型 将 映 射 为 [0.0,<br />

[-1.0, 整 型 将 映 射 为 号 符<br />

如 , 一 个<br />

0xff 为 值<br />

8 号 符 无<br />

不 执 行 任 何<br />

4.5.3.9 介<br />

N) 范<br />

。 的 它<br />

维<br />

1.0) 的<br />

1)。 一<br />

维<br />

是<br />

N), 因<br />

63]<br />

了 运 行 绍 介<br />

31]<br />

在 对 应 于 坐 标 的 维 度 中 的 大 小 。 范 纹 理 纹<br />

围<br />

理 元 素 将 被 读 取 为 1; 如 果 纹<br />

是 cudaReadModeElementType,<br />

个 可 选 的 参 数 , 默 认 值 为 cudaReadModeElementType。 一<br />

在 归 一 化 的 坐 标 内 , 同 般 情 况 下 , 纹 理 坐 标 与 纹 理 大 小 无 关 , 规 范 化 的 纹 理 坐 标 通 此<br />

<strong>CUDA</strong><br />

(clamp):<br />

编<br />

19<br />

执 行 低 精 度 插 值 。 在 启 用 时 , 视<br />

理 参 考 的 其 他 属 性 是 可 变 的 , 可 通 过 宿 主 运 行 时 在 运 行 时 更 改 ( 们 指 定 纹 理 坐 标 是 否 为 归 一 化 的 滤 , 下 面 将 介 绍 相 关 内 容 围 内 的 浮 点 坐 标 引 用 纹 理 , 其 中 纹<br />

如 , 有 一 个 大 小 例<br />

N 的<br />

(normalized)<br />

第 4.5.2.6<br />

时 API,<br />

了 驱 动 程 序 API)。 绍<br />

, 以 及 寻 址 模 式 和 纹 理 过<br />

理 的 寻 址 范 围 在 x<br />

N) 范<br />

[0, 情 况 下 , 使 用 认 默<br />

1.0) 内<br />

使 用 归 一 化 在<br />

被 的<br />

被<br />

为 64x32<br />

x , 在 理 纹<br />

y<br />

[0, 用 此 纹 理 时 坐 标 分 别 处 于 引 度<br />

将 被 调 整 到 范 址 往 往 在 纹 理 包 含 周 期 信 号 时 使 用 。 它 仅 使 用 纹 理 值<br />

[0,<br />

[0.0, 归 一 化 的 纹 理 坐 标 将 在 。 内<br />

[0, 内 指 定 , 而 非 围 范<br />

一 64x32<br />

寻 址 模 式<br />

足 以 满 足 一 些 应 用 程 序 的 需 求 。 小 常<br />

y<br />

[0, 为 均 度<br />

围 [0.0,<br />

2.0 南 , 版 本 指 程<br />

[0, 模 式 定 义 在 纹 理 坐 标 超 出 范 围 时 将 出 现 怎 样 的 情 况 。 在 使 用 非 归 一 化 纹 理 坐 标 时 , 超 出 址 寻<br />

纹 理 坐 标 将 被 调 整<br />

于 0<br />

被 设 置 为 0, 大 于 或 等 值<br />

于 N<br />

被 设 置 为 N-1。 值<br />

0.0 坐 标 时 , 默 认 寻 址 模 式 也 是 调 整 坐 标 : 小 于 理 纹<br />

1.0 于 大<br />

为 0.75.<br />

一 化 坐 标 , 也 可 指 定 坐 标 的 一 部 分 , 例 如 归<br />

视<br />

为 0.25,-1.25<br />

texel 纹 理 过 滤 只 能 对 配 置 为 返 回 浮 点 数 据 的 纹 理 进 行 。 这 将 在 相 邻 性 线


提<br />

节<br />

前<br />

将<br />

数<br />

选<br />

。<br />

节<br />

节<br />

(intrinsic 函 function)<br />

间<br />

的 位 置 进 行 插 值 。<br />

。<strong>CUDA</strong> 分<br />

4.3.4.3 来 自 线 性 存 储 器 的 纹 理 与 来 自 <strong>CUDA</strong> 数 组 的 纹 理<br />

于 一 维 纹 理 执 行 简 单 的 线 性 插 值 , 而 对 于 二 维 纹 理 则 执 行 双 线 性 插 值 。 对<br />

texel 纹 理 拾 取 位 置 周 围 的 于 位<br />

texel 取 , 纹 理 拾 取 的 返 回 值 将 根 据 纹 理 坐 标 在 读 被<br />

D 录 附<br />

了 关 于 纹 理 拾 取 的 更 多 细 节 。 供<br />

<br />

<br />

<br />

<br />

仅 不 维<br />

的 任 意 区 域 ( 参 见 在 线 性 存 储 器 内 分 配 的 纹 理 : 度 仅 能 为 1; 组 纹 理 过 滤 ; 可 使 用 非 归 一 化 整 型 纹 理 坐 标 寻 址 ; 支 持 多 种 寻 址 模 式 : 超 出 范 围 的 纹 理 访 问 将 返 回 零 。<br />

第 4.5.1.2<br />

)。<br />

配 例 程 返 回<br />

4.4 设 备 运 行 时 组 件<br />

cudaBindTexture()/cuTexRefSetAddress()<br />

会 对 纹 理 基 址 实 施 对 齐 要 求 。 为 了 抽 象 这 种 来 自 程 序 员 的 对 齐 要 求 , 绑 定 设 备 存 储 器 上 的 纹 理 参 考 的 函 数 将 传 回 一 个 字 节 偏 移 , 必 须 将 其 到 纹 理 拾 取 , 之 后 才 能 读 取 所 需 的 存 储 器 的 基 址 指 针 符 合 这 种 对 齐 限 制 , 因 此 应 用 程 序 可 通 过 向 件 硬<br />

<strong>CUDA</strong> 可 以 是 线 性 存 储 器 或 理 纹<br />

4.4.1 数 学 函 数<br />

递 所 分 配 的 指 针 来 完 全 避 免 偏 移 传<br />

备 运 行 时 组 件 仅 可 用 于 设 备 函 数 设<br />

误 差 范 围 。<br />

B.1 于 对<br />

介 绍 的 部 分 函 数 而 言 , 设 备 运 行 时 组 件 中 存 在 准 确 性 略 低 而 速 度 更 快 的 版 本 ; 其 名 称 相 同 ,<br />

。<br />

4.4.2 同 步 函 数<br />

void __syncthreads();<br />

__syncthreads() 用<br />

步 块 中 的 所 有 线 程 。 一 旦 所 有 线 程 均 达 到 此 同 步 点 , 才 将 继 续 执 行 后 续 代 码 。 于 协 调 同 一 个 块 内 的 线 程 间 通 信 。 在 一 个 块 内 的 某 些 线 程 访 问 共 享 或 全 局 存 储 器 中 的 相 同<br />

__syncthreads() 允<br />

地 址 时 , 部 分 访 问 操 作 可 能 存 在 写 入 后 读 取 、 读 取 后 写 入 或 写 入 后 写 入 之 类 的 风 险 。 可 通 过 在 这 些 访 问 操 作 间 同 步 线 程 来 避 免 这 些 数 据 风 险 。 许 在 条 件 代 码 中 使 用 , 但 仅 当 条 件 估 值 在 整 个 线 程 块 中 都 相 同 时 才 允 许 使 用 , 否 则 代 码 执 行 将 有 可 能 挂 起 , 或 者 出 现 意 料 之 外 的 副 作 用 。 同<br />

(-use_fast_math) 器 有 一 个 译 编<br />

项 , 用 于 强 制 要 求 所 有 函 数 编 译 其 准 确 性 略 低 的 版 本 ( 如 果 存 在 )。<br />

但 带 有 一 个 __<br />

__sinf(x))。B.2 如 ( 缀<br />

列 举 了 这 些 内 建<br />

数 , 还 列 举 了 它 们 的 对 应<br />

20 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


列<br />

数<br />

(atomic<br />

,atomicAdd() 将 对 function)<br />

元<br />

元<br />

和<br />

访<br />

节<br />

位<br />

位 位<br />

修<br />

写<br />

4.4.3 纹 理 函 数<br />

4.4.3.1 来 自 线 性 存 储 器 的 纹 理<br />

系<br />

template<br />

Type tex1Dfetch(<br />

texture texRef,<br />

int x);<br />

float tex1Dfetch(<br />

texture texRef,<br />

int x);<br />

float tex1Dfetch(<br />

texture texRef,<br />

int x);<br />

float tex1Dfetch(<br />

texture texRef,<br />

int x);<br />

float tex1Dfetch(<br />

texture texRef,<br />

int x);<br />

拾<br />

的<br />

tex1Dfetch() 来 自 线 性 存 储 器 的 纹 理 , 通 过 于 对<br />

函 数 访 问 纹 理 , 示 例 如 下 : 列<br />

float4 tex1Dfetch(<br />

texture texRef,<br />

说 , 这 些 函 数 可 选 择 将 整 型 转 变 为 单 精 度 浮 点 类 型 。 来 型 整 于 对 。 式<br />

int x);<br />

拾<br />

的<br />

4.4.3.2 来 自 <strong>CUDA</strong> 数 组 的 纹 理<br />

x 函 数 会 使 用 纹 理 坐 标 些 这<br />

texRef 定 到 纹 理 参 考 绑 取<br />

线 性 存 储 器 区 域 。 不 支 持 纹 理 过 滤 和 寻 址 模<br />

2 上 述 函 数 以 外 , 还 支 持 了 除<br />

4 和 组<br />

, 示 例 如 下 : 组<br />

template<br />

Type tex1D(texture texRef,<br />

float x);<br />

template<br />

Type tex2D(texture texRef,<br />

float x, float y);<br />

template<br />

Type tex3D(texture texRef,<br />

float x, float y, float z);<br />

和<br />

拾<br />

的<br />

数<br />

x 示 例 将 使 用 纹 理 坐 标 上 以<br />

texRef 定 到 纹 理 参 考 绑 取<br />

性 存 储 器 。 线<br />

<strong>CUDA</strong> 来 自 于 对<br />

tex1D()、tex2D()、tex3D() 纹 理 , 可 通 过 的 组<br />

纹 理 : 问<br />

4.4.4 原 子 函 数<br />

。 纹 理 参 考 的 不 变 ( 编 译 时 ) 和 可 变 ( 运 行 时 ) 属 性 相 互 结 合 , 共 同 确 定 坐 标 的 解 释 方 式 、 在 纹 理 拾 取 过 程 中 发 生 的 处 理 以 及 纹 组<br />

将 结 果 写 回 同 一 地 址 。 之 所 以 说 这 样 的 操 作 是 原 子 的 , 是 因 为 它 可 在 不 干 扰 其 他 线 程 的 前 提 下 执 行 。 换 句<br />

<strong>CUDA</strong> 编<br />

21<br />

x、y 函 数 将 使 用 纹 理 坐 标 些 这<br />

z<br />

texRef 定 到 纹 理 参 考 绑 取<br />

<strong>CUDA</strong><br />

4.3.4.1 取 所 提 供 的 返 回 值 ( 参 见 第 拾 理<br />

第 4.3.4.2<br />

)。<br />

原 子 函 数<br />

32 全 局 或 共 享 存 储 器 内 的 一 个 于 位<br />

或 64<br />

- 行 读 取 执 字<br />

- 入 原 子 改<br />

2.0 南 , 版 本 指 程<br />

操 作 。 例 如<br />

32 局 或 共 享 存 储 器 内 的 某 个 地 址 读 取 全 在<br />

字 , 将 其 与 一 个 整 型 相 加 , 并<br />

说 , 在 操 作 完 成 前 , 其 他 任 何 线 程 都 无 法 访 问 此 地 址 。 话<br />

C 录 附<br />

举 了 受 支 持 的 所 有 原 子 函 数 。 如 附 录 所 述 , 并 非 所 有 设 备 都 支 持 这 些 函 数 。 具 体 来 说 , 计 算 能


的<br />

块<br />

块<br />

,<strong>CUDA</strong> 驱<br />

都<br />

的 和<br />

运<br />

节 配<br />

是<br />

是<br />

需<br />

动<br />

动<br />

。<br />

。<br />

节<br />

是<br />

对<br />

。 数<br />

驱<br />

均<br />

零 时 返 回 非 零 值 。 非 零 时 返 回 非 零 值 。 非<br />

节<br />

的<br />

节<br />

前<br />

前<br />

。nvcc<br />

运 生<br />

宿<br />

驱<br />

的<br />

4.4.5 Warp vote 函 数<br />

用 于 有 符 号 和 无 符 号 整 型 ( 适 仅 作 操 子 原<br />

函 数<br />

备 不 支 持 任 何 原 子 函 数 设<br />

或<br />

int __all(int predicate);<br />

vote 函<br />

int __any(int predicate);<br />

1.0 为 力<br />

一 个 例 外 情 况 , 它 支 持 单 精 度 浮 点 数 )。<br />

但 atomicExch()<br />

的 所 有 线 程 计<br />

4.5 宿 主<br />

内<br />

宿 主 运 行 时 组 件<br />

当 1.2 计 算 能 力 为 有 只<br />

Warp 的 设 备 支 持 高 更<br />

为 warp<br />

<br />

<br />

<br />

<br />

<br />

代 设<br />

<br />

<br />

上 存 纹 执<br />

与<br />

有 宿 主 函 数 才 能 使 用 宿 主 运 行 时 组 件 备 管 理 只<br />

文 储 器 管 理 ; 下<br />

算 predicate,<br />

predicate 当 所 有 线 程 的 仅 且<br />

为 warp<br />

的 所 有 线 程 计 算 predicate, 内<br />

predicate 当 任 意 线 程 的 仅 且<br />

提 供 了 具 有 以 下 功 能 的 函 数 :<br />

; 它<br />

模 块 管 理 ; 行 控 制 码<br />

<br />

一<br />

参 考 管 理 ; 互 操 作 性 驱 动 程 的 理<br />

的 是 运<br />

<strong>CUDA</strong> 运<br />

OpenGL<br />

Direct3D<br />

包 含 两 个 API: 它<br />

。<br />

<strong>CUDA</strong> 称 为 个 一<br />

础 之 上 实 现 的 成 基<br />

序 API<br />

级 API; 低<br />

<strong>CUDA</strong> 为 称 个<br />

API 时 行<br />

级 API, 高<br />

<strong>CUDA</strong> 在 是<br />

API 序 程 动<br />

。<br />

API 个 两 这<br />

互 斥 的 : 一 个 应 用 程 序 仅 能 使 用 其 中 之 一 行 时 提 供 了 隐 式 初 始 化 、 上 下 文 管 理 和 模 块 管 理 , 从 而 简 化 了 设 备 代 码 管 理 它<br />

的 C<br />

<strong>CUDA</strong> 码 基 于 代 主<br />

<strong>CUDA</strong> 驱<br />

4.2.5 ( 请 参 见 第 时 行<br />

。<br />

相 反<br />

API。<br />

<strong>CUDA</strong> 运<br />

API 序 程 动<br />

<strong>CUDA</strong> 此 链 接 到 此 代 码 的 应 用 程 序 必 须 使 用 因 ),<br />

时 行<br />

22 <strong>CUDA</strong><br />

提 供 了 枚 举 系 统 上 可 用 设 备 、 查 询 其 属 性 、 为 内 核 执 行 选 择 一 个 设 备 的 函 数 ( 运 行 编<br />

cubin 还 具 有 独 立 于 语 言 的 特 点 , 因 为 它 仅 处 理 外 此<br />

4.5.1 一 般 概 念<br />

4.2.5 请 参 见 第 ( 象<br />

<strong>CUDA</strong> 体 来 说 , 使 用 具 )。<br />

API 程 序 动 驱<br />

的 代 码 数 量 更 多 , 编 程 和 调 试 更 加 困 难 , 但 提 供 了 更 出 色 的 控 制 级 别 , 置 和 启 动 内 核 的 难 度 更 大 , 因 为 执 行 配 置 和 内 核 参 数 必 须 通 过 显 式 函 数 调 用 来 指 定 , 而 要<br />

库 提 供 的 , 其 所 有 入 口 点 都 带 缀 。 态<br />

4.2.3 利 用 第 能 不<br />

态 库 提 供 的 , 其 所 有 入 口 点 都 带<br />

4.5.2.9 的 执 行 配 置 语 法 。 此 外 , 设 备 模 拟 ( 请 参 见 第 绍 介<br />

<strong>CUDA</strong> 适 用 于 不 )<br />

有 cuda<br />

程 序 API。 动<br />

API 序 程 动<br />

nvcuda 过 通<br />

4.5.1.1 设 备<br />

有 cu<br />

API 时 行<br />

cudart 过 通<br />

2.0 南 , 版 本 指 程<br />

API 种 两<br />

时 API


Direct3D 互 。<br />

节<br />

和<br />

函<br />

节<br />

,Direct3D<br />

位<br />

节<br />

的<br />

(linear 或 memory)<br />

9.0。<br />

和<br />

实<br />

数<br />

,<strong>CUDA</strong><br />

启<br />

节<br />

)。<br />

arrays)。<br />

(<strong>CUDA</strong><br />

节<br />

。<strong>CUDA</strong><br />

与<br />

、16<br />

数<br />

个<br />

4.5.1.2 存 储 器<br />

程 可 在 同 一 个 设 备 上 执 行 设 备 代 码 , 但 根 据 设 计 , 一 个 宿 主 线 程 只 能 在 一 个 设 备 上 执 行 设 备 代 线 主 宿 个 多<br />

存 储 器<br />

4.5.2.2 内 容 请 参 见 第 关 相<br />

API 动 程 序 驱 ,<br />

4.5.3.2 内 容 请 参 见 第 关 相<br />

<strong>CUDA</strong> 数<br />

<strong>CUDA</strong> 因 而 , 需 要 多 个 在 多 个 设 备 上 执 行 设 备 代 码 。 此 外 , 通 过 一 个 宿 主 线 程 的 运 行 时 创 建 的 资 源 无 法 由 来 自 其 他 宿 主 线 程 的 运 行 时 使 用 。 。 码<br />

32 位<br />

位<br />

个<br />

支<br />

位<br />

数<br />

位<br />

位<br />

设 备 存 储 器 可 指 派 为 线 性 存 储 器<br />

<strong>CUDA</strong><br />

组<br />

32 上 的 线 性 存 储 器 位 于 备 设<br />

地 址 空 间 内 , 因 此 , 独 立 分 配 的 实 体 可 通 过 指 针 引 用 另 外 一 个 实 体 , 比 如 ,<br />

4.3.4 存 储 器 布 局 是 不 透 明 , 专 为 纹 理 拾 取 而 优 化 ( 参 见 第 的 组<br />

)。 它 们 可 以 是 一 维 、 二 维 或<br />

分<br />

1、2、4 的 , 由 元 素 组 成 , 这 些 元 素 包 含 维 三<br />

8 , 这 些 分 量 可 以 是 有 符 号 或 无 符 号 的 量 分<br />

或<br />

4.5.1.3 OpenGL 互 操 作 性<br />

的 (page-locked)<br />

16 , 也 可 以 是 型 整<br />

API ( 当 前 仅 有 驱 动 程 序 点 浮<br />

32 或 ) 持<br />

浮 点<br />

组 仅 可 由 内 核<br />

OpenGL 缓<br />

(buffer 可 能<br />

object)<br />

使 的<br />

节<br />

能<br />

实 写<br />

4.5.2.3 可 通 过 第 主 宿<br />

第 4.5.3.6<br />

<strong>CUDA</strong> 的 存 储 器 复 制 函 数 读 取 和 写 入 线 性 存 储 器 和 绍 介<br />

。 组<br />

储 器 和 设 备 存 储 器 之 间 的 带 宽 较 高 —— 但 仅 针 对 宿 主 存 储 器 的 宿 主 线 程 所 执 行 的 数 据 传 输 。 分 页 锁 定 的 存 储 器 是 一 种 稀 缺 资 源 , 因 此 分 页 锁 定 存 储 器 中 的 分 配 将 先 于 可 分 页 存 储 器 的 分 配 而 出 错 。 此 外 , 由 于 减 少 了 操 作 系 统 可 用 于 分 页 的 物 理 存 储 器 数 量 , 分 配 过 多 的 分 页 锁 定 存 储 器 将 降 低 整 体 系 统 性 能 。 存<br />

分 页 存 储 器 恰 好 相 反 。 分 页 锁 定 存 储 器 的 优 势 之 一 在 于 , 如 果 将 宿 主 存 储 器 指 派 为 分 页 锁 定 存 储 器 , 宿 主<br />

宿 主 运 行 时 还 提 供 了 函 数 来 分 配 和 释 放 分 页 锁 定<br />

— 存 储 器 主 宿<br />

malloc()<br />

配 的 普 通 可<br />

二 进 制 树 内 。 在<br />

过 纹 理 拾 取 读 取 , 仅 可 绑 定 到 具 有 相 同 分 量 数 的 纹 理 参 考 。 通<br />

4.5.1.4 Direct3D 互 操 作 性<br />

Direct3D<br />

<strong>CUDA</strong> 能 资<br />

使 实 的<br />

节<br />

能<br />

实 写<br />

使<br />

冲 对 象<br />

<strong>CUDA</strong> 到 射 映<br />

<strong>CUDA</strong> 空 间 , 从 而 使 址 地<br />

OpenGL 取 读 够<br />

入<br />

<strong>CUDA</strong> 据 或 使 数 的<br />

OpenGL 入 数 据 供 写 够<br />

4.5.2.7 第 。 用<br />

API 了 如 何 通 过 运 行 时 述 描<br />

现 此 目<br />

4.5.3.10 第 , 标<br />

API 了 如 何 通 过 驱 动 程 序 述 描<br />

此 目 标 。 现<br />

cuD3D9RegisterResource() 参<br />

API 了 如 何 通 过 驱 动 程 序 现 此 目 标 对 于 可 映 射 哪 些 资 源 的 限 制 条 件 , 请 参 考 手 册 。 介 绍<br />

设 设<br />

<strong>CUDA</strong><br />

GPU 上 上<br />

上 见<br />

cudaD3D9RegisterResource()<br />

目 标 , 同 一 节 还 和 此 现<br />

设<br />

标<br />

文 一 次 仅 可 与 一 创 建 的 。 此 外 下<br />

备 互 操 作<br />

下 文<br />

备 必 须 是 在 同 一<br />

<strong>CUDA</strong> 映 射 到 可 源<br />

地 址 空 间 , 从 而<br />

使 <strong>CUDA</strong><br />

Direct3D 取 读 够<br />

入 的 数 据 , 或 者<br />

记<br />

Direct3D 入 数 据 供 写 够<br />

4.5.2.8 第 。 用<br />

API 了 如 何 通 过 运 行 时 述 描<br />

<strong>CUDA</strong> 编<br />

为 了 促 进 宿 主 和 设 备 之 间 的 并 发 执 行 , 某 些 运 行 时 函 数 是 异 步 的 : 控 制 将 在 设 备 完 成 所 请 求 的 任 务 之 前 返<br />

23<br />

操 作 性 目 前 仅 支<br />

4.5.1.5 异 步 并 发 执 行<br />

<br />

执 通<br />

后<br />

个 Direct3D<br />

持 Direct3D<br />

和 Direct3D<br />

回 应 用 程 序 。 此 类 函 数 包 括<br />

D3DCREATE_HARDWARE_VERTEXPROCESSING 创 建 时 必 须 使 用 在 备<br />

:<br />

过 __global__<br />

cuLaunchGrid() 或 数<br />

cuLaunchGridAsync()<br />

的 内 核 ; 动<br />

2.0 南 , 版 本 指 程<br />

Async 储 器 复 制 和 带 有 存 行<br />

的 函 数 ; 缀


节 来<br />

不<br />

(stream)<br />

后<br />

应<br />

实<br />

和<br />

;<br />

提 的 和 的<br />

将 的<br />

节 实<br />

环<br />

来 调 并<br />

节<br />

节<br />

数<br />

的<br />

操<br />

的<br />

实<br />

的 使 的<br />

和<br />

实<br />

应<br />

<br />

设 执<br />

设 备 与 设 备 间 双 向 存 储 器 复 制 的 函 数 置 存 储 器 的 函 数 。 某 些 设 备 还 可 在 分 页 锁 定 的 宿 主 存 储 器 和 设 备 存 储 器 之 间 执 行 复 制 , 且 与 内 核 执 行 并 发 地 执 行 此 类 复 制 操 行<br />

4.5.2.4 节<br />

。 如 果 使 用 的 是 运 行 时 API,<br />

则 请 参 请 ) 分 配 的 二 维 数 组 的 存 储 器 复 制 。 作<br />

流 的 定 义 方 法 是 创 建 流 对 象 , 并 将 其 指 定 为 内 核 启 动 和 宿 主 与 设 备 间 内 存 双 向 复 制 序 列 的 流 参 数 。 管<br />

的<br />

为<br />

第<br />

cudaGetDeviceProperties() 序 可 通 过 调 用 程 用<br />

deviceOverlap 查 检<br />

询 此 功 能 ; 如 果 使 用 的 是 驱 动 程 序 API, 查<br />

CU_DEVICE_ATTRIBUTE_GPU_OVERLAP 过 使 用 通 可<br />

用 cuDeviceGetAttribute()<br />

<strong>CUDA</strong> 。 此 功 能 当 前 仅 支 持 不 涉 及 询 查<br />

或 通 过 cudaMallocPitch()( 组<br />

4.5.2.3 第 见<br />

或 cuMemAllocPitch()( )<br />

4.5.3.6 第 见 参<br />

用 程 序 通 过 流 理 并 发 。 流 就 是 按 顺 序 执 行 的 一 系 列 操 作 。 另 一 方 面 , 不 同 的 流 可 与 其 他 流 乱 序 执 行 其 操 作 , 也 可 并 发 执 行 。 应<br />

API 了 如 何 通 过 运 行 时 述 描<br />

4.5.3.7 目 标 , 第 此 现<br />

API 了 如 何 通 过 驱 动 程 序 述 描<br />

现 此 目<br />

。 不 带 流 参 数 或 使 用 零 作 为 流 参 数 的 任 何 内 核 启 动 、 存 储 器 设 置 或 存 储 器 复 制 函 数 都 仅 能 在 此 前 的 操 作 完 成 标<br />

API<br />

始 包 括 作 为 流 部 分 的 操 作 , 而 在 此 类 函 数 完 成 之 前 , 无 法 启 动 任 何 后 续 操 作 。 无 流 参 数 的 内 核 启 动 , 缀 的 存 储 器 复 制 都 将 被 指 派 给 默 认 零 流 种 方 法 , 使 其 能 够 了 解 一 个 流 中 的 之 前 全 部 操 作 是 否 已 完 成 。 用 于 运 行 时 开 后<br />

无 Async<br />

有 操 作 完 成 。 类 似 地 , 用 于 运 行 所<br />

API 运 行 时 于 用<br />

cudaStreamQuery()<br />

用 于 驱 动 程<br />

应 用 程 序 提 供 了 一<br />

序 API<br />

cuStreamQuery()<br />

cudaStreamSnchronize()<br />

API 于 驱 动 程 序 用 和<br />

cuStreamSynchronize()<br />

了 一 种 方 法 , 可 显 式 强 制 要 求 运 行 时 等 待 流 中 之 前 的 应 用 程 序 能 够 强 制 要 求 运 行 时 等 待 所 有 流 中 的 所 有 之 前 设 备 任 务 完 成 。 为 了 避 免 不 必 要 的 减 速 , 最 好 将 这 些 供<br />

待 给 定 流 内 之 前 的 所 有 任 务 完 成 , 之 后 再 销 毁 流 , 并 将 控 制 返 回 给 等<br />

操<br />

时 API<br />

cudaThreadSynchronize()<br />

API 驱 动 程 序 于 用<br />

cuCtxSynchronize()<br />

API 序 宿 主 线 程 。 运 行 时 还 提 供 了 一 种 方 法 , 可 密 切 监 控 设 备 的 进 度 并 执 行 准 确 的 计 时 , 它 允 许 应 用 程 序 异 步 记 录 程 序 内 任 意 点 的 事 件 , 并 查 询 这 些 事 件 的 实 际 记 录 事 件 。 一 个 事 件 将 在 先 于 该 事 件 的 所 有 任 务 ( 也 可 以 是 给 定 流 中 程 动<br />

cuStreamDestroy()<br />

函 数 用 于 计 时 或 者 隔 离 失 败 的 启 动 或 存 储 器 复 制 操 作 。 用 于 运 行 时 API<br />

cudaStreamDestroy()<br />

用 于 驱<br />

4.5.2 运 行 时 API<br />

果 宿 主 线 程 在 来 自 不 同 流 的 两 项 操 作 之 间 调 了 分 页 锁 定 的 宿 主 存 储 器 分 配 、 设 备 存 储 器 分 配 、 设 备 存 局 禁 用 异 步 执 行 。 此 特 性 仅 为 调 试 提 供 , 不 应 用 于 使 生 产 软 件 更 可 靠 运 行 之 目 的 。 如<br />

/ 有 操 作 ) 均 已 完 成 时 记 录 。 零 流 中 的 事 件 将 在 设 备 完 成 来 自 所 有 流 的 之 前 任 务 作 后 记 录 。 所 的<br />

第 4.5.2.5<br />

4.5.2.1 初 始 化<br />

API 描 述 如 何 通 过 运 行 时 将 节<br />

4.5.3.8 目 标 , 第 此 现<br />

API 述 如 何 通 过 驱 动 程 序 描 将<br />

此 目 标 。 现<br />

<strong>CUDA</strong> 设 置 、 设 备 与 设 备 之 间 的 双 向 存 储 器 复 制 或 零 流 的 任 何 器 储<br />

, 则 这 两 项 操 作 无 法 并 行 执 行 。 作<br />

4.5.2.2 设 备 管 理<br />

<strong>CUDA</strong>_LAUNCH_BLOCKING 员 可 将 序 程<br />

变 量 设 置 为 1, 从 而 为 系 统 上 运 行 的 所 境<br />

有 <strong>CUDA</strong><br />

用 程 序 全<br />

cudaGetDeviceCount() 和<br />

提<br />

API 时 行 运<br />

存 在 显 式 初 始 化 函 数 ; 它 将 在 运 行 时 函 数 被 首 次 调 用 时 初 始 化 。 需 要 牢 记 , 在 计 时<br />

int deviceCount;<br />

cudaGetDeviceCount(&deviceCount);<br />

其 属 性 : 索<br />

24 <strong>CUDA</strong> 编<br />

运 行 时 调 用 发 生 时 , 或 解 释 来 自 第 一 次 运 行 时 调 用 的 错 误 码 时 , 即 进 行 初 始 化 。<br />

(timing)<br />

cudaGetDeviceProperties()<br />

供 了 一 种 方 法 , 用 于 枚 举 这 些 设 备 并 检<br />

2.0 南 , 版 本 指 程


的<br />

分<br />

个<br />

、cudaMallocPitch() 分<br />

数<br />

。 用<br />

节<br />

、<strong>CUDA</strong> 数<br />

int device;<br />

for (device = 0; device < deviceCount; ++device) {<br />

cudaDeviceProp deviceProp;<br />

cudaGetDeviceProperties(&deviceProp, device);<br />

}<br />

cudaSetDevice() 于 选 择 与 宿 主 线 程 相 关 的 设 备 : 用<br />

cudaSetDevice(device);<br />

cudaSetDevice() 完<br />

函<br />

的 4.5.2.3 存 储 器 管 理<br />

或<br />

分<br />

: 释<br />

成 此 任 务 , 将 自 动 选 中 设<br />

__global__ 首 先 选 择 设 备 , 之 后 才 能 调 用 须 必<br />

API 任 何 来 自 运 行 时 或 数<br />

数 。 如 果 未 通 过 显 式 调 任 何 显 式 调 用 都 将 无 效 函<br />

cudaSetDevice() 随 后 对 0, 备<br />

float* devPtr;<br />

cudaMalloc((void**)&devPtr, 256 * sizeof(float));<br />

// host code<br />

float* devPtr;<br />

int pitch;<br />

点 元 素 的 数 组 因<br />

cudaMallocPitch((void**)&devPtr, &pitch,<br />

浮<br />

width * sizeof(float), height);<br />

myKernel(devPtr, pitch);<br />

// device code<br />

__global__ void myKernel(float* devPtr, int pitch)<br />

{<br />

for (int r = 0; r < height; ++r) {<br />

float* row = (float*)((char*)devPtr + r * pitch);<br />

for (int c = 0; c < width; ++c) {<br />

float element = row[c];<br />

}<br />

}<br />

}<br />

<strong>CUDA</strong><br />

cudaCreateChannelDesc() 创 分 数<br />

释<br />

。 放<br />

。cudaMallocArray() 需<br />

cudaMalloc() 存 储 器 是 使 用 性 线<br />

cudaMallocPitch()<br />

cudaFree() , 使 用 的 配<br />

256 示 例 代 码 将 在 线 性 存 储 器 中 分 配 一 个 包 含 下 以<br />

议 在 分 配 二 维 数 组 时 使 用 cudaMallocPitch(), 建<br />

5.1.2.1 能 确 保 合 理 填 充 已 分 配 的 存 储 器 , 满 足 第 它 为<br />

绍 的 对 齐 要 求 , 从 而 确 保 访 问 行 地 址 或 执 行 二 维 数 组 与 设 备 存 储 器 的 其 他 区 域 之 间 的 复 制 ( 使 用<br />

cudaMemcpy2D()) 时 获 得 最 优 性 能 。 所 返 回 的 间 距 ( 或 步 幅 ) 必 须 用 于 访 问 数 组 元 素 。 以 下 代 码 示 例 将 分 介<br />

widthxheight 个 一 配<br />

维 浮 点 值 数 组 , 并 显 示 如 何 在 设 备 代 码 中 循 环 遍 历 数 组 元 素 : 二<br />

的<br />

数<br />

位<br />

cudaChannelFormatDesc channelDesc =<br />

cudaCreateChannelDesc();<br />

cudaArray* cuArray;<br />

cudaMallocArray(&cuArray, &channelDesc, width, height);<br />

cudaGetSymbolAddress() 用<br />

的 格 式 描 述 。 建<br />

获<br />

cudaMallocArray() 使 用 是 组<br />

cudaFreeArray() , 使 用 的 配<br />

放<br />

使 用 要<br />

考 手 册 列 举 了 用 于 配 的 线 性 存 储 器 组 和 为 全 局 或 常 量 存 储 器 空 间 中 声 明 的 变 量 分 配 的 存 储 器 之 间 复 制 存 储 器 的 所 有 函 数 。 参<br />

widthxheight 代 码 示 例 分 配 了 一 个 下 以<br />

<strong>CUDA</strong><br />

32 包 含 一 个 , 组<br />

浮 点 组 件 : 的<br />

cudaGetSymbolSize()<br />

索 指 向 为 全 局 存 储 器 空 间 中 声 明 的 变 量 分 配 的 存 储 器 的 地 址 。 所 分 配 存 储 器 的 大 小 是 通 过 取 的 。<br />

cudaMemcpy2DToArray(cuArray, 0, 0, devPtr, pitch,<br />

检 于<br />

width * sizeof(float), height,<br />

cudaMemcpyDeviceToDevice);<br />

<strong>CUDA</strong> 编<br />

:<br />

25<br />

在 cudaMalloc()<br />

配 的 线 性 存 储 器<br />

float data[256];<br />

代 码 示 例 将 一 些 宿 主 存 储 器 数 组 复 制 到 设 备 存 储 器 中 的 面 下<br />

int size = sizeof(data);<br />

float* devPtr;<br />

cudaMalloc((void**)&devPtr, size);<br />

<strong>CUDA</strong> 的 代 码 示 例 将 二 维 数 组 复 制 到 之 前 代 码 示 例 中 分 配 的 面 下<br />

中 : 组<br />

2.0 南 , 版 本 指 程


。hostPtr<br />

cudaMemcpy(devPtr, data, size, cudaMemcpyHostToDevice);<br />

__constant__ float constData[256];<br />

float data[256];<br />

cudaMemcpyToSymbol(constData, data, sizeof(data));<br />

4.5.2.4 流 管 理<br />

面 的 代 码 示 例 将 一 些 宿 主 存 储 器 数 组 复 制 到 常 量 存 储 器 中 : 下<br />

cudaStream_t stream[2];<br />

for (int i = 0; i < 2; ++i)<br />

cudaStreamCreate(&stream[i]);<br />

:<br />

for (int i = 0; i < 2; ++i)<br />

cudaMemcpyAsync(inputDevPtr + i * size, hostPtr + i * size,<br />

size, cudaMemcpyHostToDevice, stream[i]);<br />

for (int i = 0; i < 2; ++i)<br />

myKernel<br />

(outputDevPtr + i * size, inputDevPtr + i * size, size);<br />

for (int i = 0; i < 2; ++i)<br />

cudaMemcpyAsync(hostPtr + i * size, outputDevPtr + i * size,<br />

size, cudaMemcpyDeviceToHost, stream[i]);<br />

cudaThreadSynchronize();<br />

数 的<br />

下 代 码 示 例 创 建 两 个 流 这 些 流 均 通 过 以 下 代 码 示 例 定 义 为 一 个 任 务 序 列 , 包 括 一 次 从 宿 主 到 设 备 的 存 储 器 复 制 、 一 次 内 核 启 动 、 以<br />

次 从 设 备 到 宿 主 的 存 储 器 复 制 : 一<br />

myKernel()<br />

允 处<br />

复<br />

必 的<br />

float* hostPtr;<br />

器 , 这 样 才 能 同 时 执 行 : 储 存 主<br />

cudaMallocHost((void**)&hostPtr, 2 * size);<br />

hostPtr 流 均 会 将 其 输 入 数 组 个 两<br />

inputDevPtr 分 复 制 到 设 备 存 储 器 的 部 一<br />

中 , 通 过 调 用 组<br />

cudaStreamSynchronize()<br />

cudaStreamDestroy() 可 可<br />

并<br />

目<br />

设 备 上 的 inputDevPtr, 理<br />

outputDevPtr 果 结 将<br />

hostPtr 回 制<br />

相 同 部 分 。 使 用 两 个 流<br />

4.5.2.5 事 件 管 理<br />

hostPtr 理 处<br />

许 一 个 流 的 存 储 器 复 制 与 另 外 一 个 流 的 内 核 执 行 相 互 重 叠<br />

须 指 向 分 页 锁 定 的 宿<br />

cudaEvent_t start, stop;<br />

cudaEventCreate(&start);<br />

cudaEventCreate(&stop);<br />

:<br />

于 同 步 宿 主 与 特 定 流 , 允 许 其 他 流 继 续 在 该 设 备 上 执 行 。 通 过 调 用 释 放 流 。 用<br />

后 调 用 了 cudaThreadSynchronize(), 最<br />

的 是 在 进 一 步 处 理 之 前 确 定 所 有 流 均 已 完 成 。<br />

cudaEventRecord(start, 0);<br />

for (int i = 0; i < 2; ++i)<br />

cudaMemcpyAsync(inputDev + i * size, inputHost + i * size,<br />

size, cudaMemcpyHostToDevice, stream[i]);<br />

for (int i = 0; i < 2; ++i)<br />

myKernel<br />

(outputDev + i * size, inputDev + i * size, size);<br />

for (int i = 0; i < 2; ++i)<br />

cudaMemcpyAsync(outputHost + i * size, outputDev + i * size,<br />

size, cudaMemcpyDeviceToHost, stream[i]);<br />

cudaEventRecord(stop, 0);<br />

cudaEventSynchronize(stop);<br />

float elapsedTime;<br />

cudaEventElapsedTime(&elapsedTime, start, stop);<br />

面 的 代 码 示 例 创 建 了 两 个 事 件 这 些 事 件 可 用 于 为 上 一 节 的 代 码 示 例 计 时 , 方 法 如 下 : 下<br />

cudaEventDestroy(start);<br />

cudaEventDestroy(stop);<br />

26 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


定<br />

类<br />

,cudaFilterModeLinear 是<br />

<br />

<br />

在<br />

cudaChannelFormatKindUnsigned, 在<br />

(bit)<br />

cudaChannelFormatKindSigned,<br />

指<br />

定<br />

;channelDesc 的<br />

为<br />

类<br />

;addressMode 是<br />

(wrap)<br />

或<br />

;filterMode<br />

)texel 的<br />

的<br />

:<br />

和<br />

4.5.2.6 纹 理 参 考 管 理<br />

<br />

高<br />

<br />

struct textureReference<br />

{<br />

int normalized;<br />

enum cudaTextureFilterMode filterMode;<br />

enum cudaTextureAddressMode addressMode[3];<br />

struct cudaChannelFormatDesc channelDesc;<br />

}<br />

Normalized<br />

纹 理 坐 标 寻 址 , 而 指<br />

depth<br />

filterMode<br />

cudaFilterModePoint<br />

指 是<br />

纹 理 大 小 ; 定 过 滤 模 式 , 即 拾 取 根 据 输 入 的 纹 理 坐 标 计 算 的 纹 理 时 如 何 返 回 值 或 或<br />

的 纹 理 , 如 下<br />

1]<br />

型<br />

围 内 的 范<br />

于 所 返 回 的 值 为 纹 理 等<br />

级 API<br />

texture 的 义<br />

API 一 种 公 开 继 承 自 低 级 是 型<br />

textureReference 的 义<br />

其<br />

[0, 理 坐 标 是 否 为 归 一 化 形 式 ; 如 果 非 零 , 纹 理 中 的 所 有 元 素 都 将 使 用 纹 定<br />

非 [0,width-1]、[0,height-1]<br />

[0,depth-1],<br />

width、height 的 中<br />

<br />

addressMode 指<br />

如 输 入 纹 理 坐 标 的 两 个 ( 针 对 一 维 纹 理 )、 四 个 ( 针 对 二 维 纹 理 ) 或 八 个 ( 针 对 三 维 纹 理 如<br />

组 , 其 第 一 个 、 第 二 个 和 第 三 个 元 素 分 别 指 定 第 一 个 、 第 二 个 和 第 三 个 纹 理 坐 标 的 寻 址 模 式 ; 寻 址 模<br />

线 性<br />

则 所 返 回 的 值 为 纹 理 坐 标 最 接 近 则<br />

cudaFilterModeLinear;<br />

等 于 cudaFilterModePoint, 果<br />

标 最 接 近 输 入 纹 理 坐 标 的 texel; 坐<br />

等 于 cudaFilterModeLinear, 果<br />

channelDesc 描<br />

struct cudaChannelFormatDesc {<br />

int x, y, z, w;<br />

enum cudaChannelFormatKind f;<br />

};<br />

值 ; 对 于 浮 点 型 的 返 回 值 插<br />

此 此<br />

和<br />

等<br />

述 拾 取 纹 理 时 所 返 回 的 值 的 格 式<br />

型 如 下 : 类<br />

一 的 有 效 值 。 惟<br />

到 (clamp)<br />

到<br />

这 些 分 量 是 有 符 号 整 型 时 ; 这 些 分 量 是 无 符 号 整 型 时 ; :<br />

定 寻 址 模 式 , 表 明 如 何 处 理 超 出 范 围 的 纹 理 坐 标<br />

3 大 小 为 个 一<br />

数<br />

可 等 于 cudaAddressModeClamp, 式<br />

时 超 出 范 围 的 纹 理 坐 标 将 被 调 整<br />

有 效 范 围 之 内 , 也<br />

等 于 cudaAddressModeWrap, 可<br />

时 超 出 范 围 的 纹 理 坐 标 将 被 限 定<br />

效 范 围 之 内 ; 有<br />

于 规 范 化 的 纹 理 坐 标 , 仅 支 持 cudaAddressModeWrap。 对<br />

些 分 量 是 浮 点 类 型 时 。 这<br />

组 的 纹<br />

cudaChannelFormatKindFloat, <br />

normalized、addressMode 和 可 在<br />

数<br />

数<br />

x、y、z 中 其<br />

w<br />

于 返 回 值 各 分 量 的 位<br />

f 而 ,<br />

<br />

<br />

texture texRef;<br />

textureReference* texRefPtr;<br />

cudaGetTextureReference(&texRefPtr, “texRef”);<br />

cudaChannelFormatDesc channelDesc =<br />

cudaCreateChannelDesc();<br />

cudaBindTexture(0, texRefPtr, devPtr, &channelDesc, size);<br />

参 考 。 在 内 核 使 用 纹 理 参 考 从 纹 理 存 储 器 中 读 取 之 前 , 必 须 使 将 纹 理 参 考 绑 定 到 纹 理 。 理<br />

下 代 码 示 例 将 一 个 纹 理 参 考 绑 定 向 的 线 性 存 储 器 : 使 用 低 以<br />

texture texRef;<br />

cudaBindTexture(0, texRef, devPtr, size);<br />

数<br />

filterMode<br />

<strong>CUDA</strong> 在 宿 主 代 码 中 修 改 。 它 们 仅 适 用 于 绑 定 到 接 直<br />

级 API:<br />

<br />

texture texRef;<br />

textureReference* texRefPtr;<br />

cudaGetTextureReference(&texRefPtr, “texRef”);<br />

cudaChannelFormatDesc channelDesc;<br />

<strong>CUDA</strong> 代 码 示 例 将 一 个 纹 理 参 考 绑 定 到 使 用 低 下 以<br />

用 cudaBindTexture()<br />

cudaBindTextureToArray()<br />

<strong>CUDA</strong> 编<br />

27<br />

到 devPtr<br />

组 cuArray:<br />

用 高 级 API: 使<br />

2.0 南 , 版 本 指 程<br />

级 API:


cudaUnbindTexture() 用 。<br />

填<br />

完<br />

及<br />

<br />

cudaGetChannelDesc(&channelDesc, cuArray);<br />

cudaBindTextureToArray(texRef, cuArray, &channelDesc);<br />

texture texRef;<br />

cudaBindTextureToArray(texRef, cuArray);<br />

4.5.2.7 OpenGL 互 操 作 性<br />

GLuint bufferObj;<br />

cudaGLRegisterBufferObject(bufferObj);<br />

返<br />

用 高 级 API: 使<br />

纹 理 绑 定 到 纹 理 参 考 时 指 定 的 格 式 必 须 与 声 明 纹 理 参 考 时 指 定 的 参 数 相 匹 配 ; 否 则 纹 理 拾 取 的 结 果 将 无 法 确 定 于 解 除 纹 理 参 考 的 绑 定 。 将<br />

GLuint bufferObj;<br />

float* devPtr;<br />

cudaGLMapBufferObject((void**)&devPtr, bufferObj);<br />

之<br />

取 完<br />

4.5.2.8 Direct3D 互 操 作 性<br />

先 必 须 将 一 个 缓 冲 对 象 注 册 到 <strong>CUDA</strong>, 首<br />

cudaGLRegisterBufferObject() 能 进 行 映 射 。 可 通 过 才 后<br />

: 成<br />

cudaGLMapBufferObject() 完 成 后 , 内 核 即 可 使 用 册 注<br />

的 设 备 存 储 器 地 址 读 取 或 写 入 缓 冲 对 象 : 回<br />

Direct3D<br />

Direct3D 设 互<br />

指<br />

cudaGLUnmapBufferObject() 映 射 是 通 过 除 解<br />

cudaGLUnregisterBufferObject() , 可 使 用 的 成<br />

注 册 。 消<br />

将<br />

资<br />

LPDIRECT3DVERTEXBUFFER9 buffer;<br />

cudaD3D9RegisterResource(buffer, cudaD3D9RegisterFlagsNone);<br />

LPDIRECT3DSURFACE9 surface;<br />

cudaD3D9RegisterResource(surface, cudaD3D9RegisterFlagsNone);<br />

cudaD3D9RegisterResource()<br />

cudaD3D9UnregisterVertexBuffer()<br />

cudaD3D9MapResources()<br />

有 较 高 的 开 销 , 通 常 仅 为 每 个 资 源 调 用 一 次 。 使 用 可 之 后 , 即 可 在 需 要 时 分 和 任 返 和 具 能 可<br />

。 备<br />

cudaD3D9SetDirect3DDevice() 性 要 求 在 执 行 其 他 任 何 运 行 时 调 用 之 前 通 过 作 操<br />

定<br />

cudaD3D9RegisterResource() 即 可 使 用 后 随<br />

Direct3D<br />

cudaD3D9ResourceGetMappedSize()<br />

cudaD3D9ResourceGetMappedPitchSlice() 返 访 、<br />

回 的 设 备 存 储 器 地 址<br />

注 册 到 <strong>CUDA</strong>: 源<br />

意 多 次 地 映 射 和 解 除 映<br />

<strong>CUDA</strong> 注 册 。 将 资 源 注 册 到 消 取<br />

void* devPtr;<br />

cudaD3D9ResourceGetMappedPointer(&devPtr, buffer);<br />

size_t size;<br />

cudaD3D9ResourceGetMappedSize(&size, buffer);<br />

cudaMemset(devPtr, 0, size);<br />

height) 的<br />

cudaD3D9ResourceGetMappedPointer() 内 核 可 使 用 回 的 大 小 和 间 距 信 息 来 读 取 和 写 入 已 映 射 的 资 源 。 通 问 已 映 射 的 资 源 将 导 致 不 确 定 的 结 果 。 射 。<br />

一 个 缓 冲 区 : 了 充<br />

使 用 别<br />

cudaD3D9UnmapResources()<br />

cudaD3D9ResourceGetMappedPitch()<br />

过 Direct3D<br />

// host code<br />

void* devPtr;<br />

cudaD3D9ResourceGetMappedPointer(&devPtr, surface);<br />

size_t pitch;<br />

cudaD3D9ResourceGetMappedPitch(&pitch, surface);<br />

dim3 Db = dim3(16, 16);<br />

dim3 Dg = dim3((width+Db.x–1)/Db.x, (height+Db.y–1)/Db.y);<br />

myKernel((unsigned char*)devPtr,<br />

width, height, pitch);<br />

// device code<br />

维 表 面 的 一 个 像 素 , 像 素 格 式 为 二<br />

28 <strong>CUDA</strong> 编<br />

0 的 代 码 示 例 使 用 面 下<br />

float4:<br />

(width, 面 的 代 码 示 例 中 , 每 个 线 程 都 访 问 大 小 为 下 在<br />

2.0 南 , 版 本 指 程


mode) emulation<br />

是 用<br />

(printf()<br />

:<br />

选<br />

因 (simulating)。<br />

(device<br />

或<br />

上<br />

。<br />

__global__ void myKernel(unsigned char* surface,<br />

int width, int height, size_t pitch)<br />

{<br />

int x = blockIdx.x * blockDim.x + threadIdx.x;<br />

int y = blockIdx.y * blockDim.y + threadIdx.y;<br />

if (x >= width || y >= height) return;<br />

float* pixel = (float*)(surface + y * pitch) + 4 * x;<br />

}<br />

4.5.2.9 使 用 设 备 模 拟 模 式 进 行 调 试<br />

于 设 备 的 代 码 , 编 程 环 境 未 包 含 任 何 本 地 调 试 支 持 , 但 附 带 了 一 种 设 备 模 拟 模 式 译 , 并 在 宿 主 上 运 行 , 允 许 程 序 员 使 用 宿 主 的 本 地 调 试 支 持 来 调 试 应 用 程 序 , 就 像 调 试 宿 主 应 用 程 序 一 样 。 对<br />

cudaErrorMixedDeviceExecution.<br />

<br />

有 宿<br />

KB 空<br />

<br />

<br />

通<br />

在 内 , 都 必 须 一 致 地 为 设 备 模 拟 或 设 备 执 行 而 编 译 。 将 为 设 备 模 拟 编 译 的 代 码 与 为 设 备 执 行 编 译 的 代 码 相 连 接 将 导 致 初 始 化 时 返 回 以 下 运 行 时 错 误 : 库<br />

设 备 模 拟 模 式 中 运 行 应 用 程 序 时 运 行 时 将 模 拟 编 程 模 型 。 对 于 线 程 块 中 的 每 一 个 线 程 , 运 行 时 都 会 在 宿 主 上 创 建 一 个 线 程 。 程 序 员 需 要 确 保 : 主 能 够 运 行 每 个 块 的 最 大 线 程 数 , 此 外 还 有 一 个 针 对 主 线 程 线 程 。 间 。 在<br />

备 模 拟 模 式 提 供 众 多 特 性 使 之 成 为 一 种 独 具 优 势 的 调 试 工 具 : 过 使 用 宿 主 的 本 地 调 试 支 持 , 程 序 员 即 可 利 用 调 试 程 序 支 持 的 所 有 特 性 , 例 如 设 置 断 点 和 检 查 数 据 。 设<br />

等<br />

出 操 作 或 打 印 到 屏 幕 )。 于 所 有 数 据 都 位 于 宿 主 上 , 因 而 可 从 设 备 或 宿 主 代 码 中 读 取 任 何 特 定 于 设 备 或 特 定 于 宿 主 的 数 据 ; 输<br />

–deviceemu 试 。 在 此 模 式 中 编 译 应 用 程 序 时 ( 使 用 调 于<br />

项 ), 设 备 代 码 将 为 宿 主 编<br />

由<br />

__DEVICE_EMULATION__ 理 宏 处 预<br />

在 此 模 式 中 定 义 的 。 一 个 应 用 程 序 的 所 有 代 码 , 包 括 所 用 的 全 部<br />

由 于 设 备 代 码 被 编 译 为 在 宿 主 上 运 行 , 因 而 可 通 过 无 法 在 设 备 上 运 行 的 代 码 扩 展 代 码 , 如 文 件 输 入 和<br />

如<br />

似 地 , 可 通 过 设 备 或 宿 主 代 码 调 用 任 何 设 备 或 宿 主 函 数 。 果 误 用 了 同 步 函 数 , 运 行 时 将 检 测 到 死 锁 情 况 。 程 序 员 必 须 牢 记 , 设 备 模 拟 模 式 的 目 的 在 于 模 拟 设 备 , 而 非 仿 真 类<br />

而 , 设 备 模 拟 模 式 在 查<br />

<br />

法 错 误 时 非 常 有 用 , 但 可 能 难 以 发 现 某 些 错 误 竞 算 找<br />

<br />

<br />

256 大 的 存 储 器 可 用 于 运 行 所 有 线 程 , 已 知 每 个 线 程 都 要 占 据 堆 栈 中 的 够 足<br />

<br />

<br />

<br />

<br />

使 用<br />

条 件 在 设 备 模 拟 模 式 中 可 能 无 法 体 现 , 因 为 同 时 执 行 的 线 程 数 量 要 比 实 际 设 备 上 少 得 多 争<br />

声 的 编 :<br />

C++<br />

上 编<br />

编<br />

解 除 指 针 对 宿 主 上 的 全 局 存 储 器 的 引 用 或 对 设 备 上 宿 主 存 储 器 的 引 用 时 , 设 备 执 行 几 乎 必 然 以 某 种 无 法 确 定 的 方 式 失 败 而 设 备 模 拟 可 能 会 得 到 正 确 。 大 多 数 时 候 , 相 同 的 浮 点 计 算 在 设 备 上 执 行 时 所 得 到 的 结 果 , 与 在 设 备 模 拟 模 式 在 宿 主 上 执 行 时 所 得 到 的 结 果 并 不 完 全 相 同 。 这 些 情 况 是 可 以 预 见 的 , 只 要 使 用 略 有 差 异 编 译 选 项 , 相 同 的 浮 点 计 在<br />

就 会 得 到 不 同 的 结 果 , 更 不 用 说 不 同 的 编 译 器 、 不 同 的 指 令 集 或 不 同 的 架 构 了 。 具 体 来 说 某 些 宿 主 平 台 会 将 单 精 度 浮 点 计 算 的 中 间 结 果 存 储 在 一 个 扩 展 精 度 寄 存 器 中 在 设 备 模 拟 模 式 中 运 行 时 , 这 可 能 会 造 成 准 确 性 的 显 著 差 异 。 发 生 这 种 情 况 时 , 程 序 员 可 尝 试 以 下 方 法 , 但 没 有 任 何 一 种 算<br />

<strong>CUDA</strong> 编<br />

29<br />

方 法 能 确 保 成 功<br />

unsigned int originalCW;<br />

_FPU_GETCW(originalCW);<br />

unsigned int cw = (originalCW & ~0x300) | 0x000;<br />

_FPU_SETCW(cw);<br />

在<br />

, 从 而 实 施 单 精 度 浮 点 计 算 : 码<br />

使<br />

volatile<br />

一 些 浮 点 变 量 , 实 施 单 精 度 存 储 ; 明<br />

用 gcc<br />

-ffloat-store<br />

器 选 项 ; 译<br />

在 Linux<br />

用 _FPU_GETCW()、 使<br />

Windows<br />

用 _controlfp(), 使<br />

用 以 下 代 码 包 围 目 标 代<br />

unsigned int originalCW = _controlfp(0, 0);<br />

_controlfp(_PC_24, _MCW_PC);<br />

: 用 使 可 也<br />

个<br />

用 Visual<br />

/Op 的 器 译<br />

/fp<br />

器 选 项 ; 译<br />

2.0 南 , 版 本 指 程<br />

24 头 处 , 为 了 存 储 控 制 字 的 当 前 值 并 更 改 它 以 使 尾 数 存 储 在 开 在<br />

中 , 可 使 用 : 位


汇<br />

是<br />

中<br />

位<br />

中<br />

,warp 块<br />

大 内 支<br />

设<br />

进 的<br />

,warp<br />

进<br />

值<br />

_FPU_SETCW(originalCW);<br />

_controlfp(originalCW, 0xfffff);<br />

(denormalized<br />

<br />

vote 函<br />

4.5.3 驱 动 程 序 API<br />

在 结 尾 处 使 用 以 下 代 码 , 恢 复 原 始 控 制 字 : 或<br />

设 备 模 拟 模 式 中 的 大 小 等 于 1。 因 而 同 。 在<br />

数 产 生 的 结 果 将 与 设 备 执 行 模 式 中 不<br />

number)。 这<br />

样 , 对 于 单 精 度 浮 点 数 , 与 计 算 设 备 不 同 ( 请 参 见 附 录 A), 宿 主 平 台 通 常 支 持 反 向 规 格 化 数 可 能 会 导 致 设 备 模 拟 和 设 备 执 行 模 式 下 存 在 显 著 差 异 , 因 为 某 些 计 算 可 能 会 在 一 种 模 式 下 产 生 有 穷 的 结 果 , 而 在 另 一 种 模 式 下 产 生 无 穷 的 结 果 。 同<br />

<strong>CUDA</strong> 驱<br />

中<br />

为 操 纵 对 象 的 函 数 。<br />

大<br />

对 象<br />

句 柄<br />

描 述<br />

API 程 序 动 驱<br />

种 基 于 句 柄 、 命 令 式 的 API: 一<br />

多 数 对 象 都 通 过 不 透 明 的 句 柄 引 用 , 此 类 句 柄 可 指 定<br />

表 4-1<br />

<strong>CUDA</strong> 了 总<br />

用 的 对 象 。 可<br />

表 4-1.<br />

序 驱 动 程 序 API<br />

中 可 用 的 对 象<br />

CUdeviceptr 储 器 存 堆<br />

存 储 器 的 指 针 备<br />

<strong>CUDA</strong> 数<br />

描 设<br />

CUdevice 备 设<br />

持 <strong>CUDA</strong><br />

备 设<br />

4.5.3.1 初 始 化<br />

CUcontext 文 下 上<br />

CPU 同 于 等 致<br />

程<br />

CUmodule 块 模<br />

等 同 于 动 态 库 致<br />

CUfunction 数 函<br />

核<br />

4.5.3.2 设 备 管 理<br />

组 CUarray<br />

上 一 维 或 二 维 数 据 的 不 透 明 容 器 , 可 通 过 纹 理 参 考 读 取 备<br />

CUtexref 参 考 理 纹<br />

如 何 解 释 纹 理 存 储 器 数 据 的 对 象 述<br />

cuDeviceGetCount() 和<br />

提<br />

API 动 程 序 驱 在<br />

cuInit() 任 何 函 数 之 前 , 都 必 须 使 用 用 调<br />

初 始 化 。 行<br />

int deviceCount;<br />

cuDeviceGetCount(&deviceCount);<br />

int device;<br />

for (int device = 0; device < deviceCount; ++device) {<br />

CUdevice cuDevice;<br />

cuDeviceGet(&cuDevice, device);<br />

int major, minor;<br />

cuDeviceComputeCapability(&major, &minor, cuDevice);<br />

}<br />

: 性 属 其 索 检 便 以 ), 册<br />

cuDeviceGet()<br />

供 了 一 种 方 法 , 可 枚 举 这 些 设 备 和 其 他 功 能 ( 详 见 参 考 手<br />

4.5.3.3 上 下 文 管 理<br />

<strong>CUDA</strong> 上<br />

进<br />

中<br />

上<br />

在 该 上 下 文 被 销 毁 时 , 系 统 将 自 动 清 除 这 些 资 源 。 除 了 模 块 和 纹 理 参 考 之 类 的 对 象 之 外 , 每 个 上 下 文 还 有<br />

30 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程<br />

CPU 类 似 于 文 下<br />

API 在 驱 动 程 序 。 程<br />

<strong>CUDA</strong> 的 所 有 资 源 和 操 作 都 封 装 在 行 执<br />

下 文 内 ,<br />

32 独 有 的 己 自<br />

Cudeviceptr 空 间 。 因 而 , 不 同 上 下 文 的 址 地<br />

引 用 不 同 的 存 储 器 位 置 。 将


节<br />

函<br />

。cuCtxPopCurrent()<br />

上<br />

(usage<br />

库<br />

以<br />

创<br />

中<br />

或<br />

来<br />

(floating)”<br />

函<br />

输<br />

:<br />

用<br />

或<br />

cuCtxPopCurrent() 都 有 一 个 当 前 上 下 文 堆 栈 将 为 任 意 宿 主 线 程 的 当 前 上 下 文 压 入 个 每<br />

cuCtxDestroy() 使 将<br />

。cuCtxCreate() 将<br />

涉 及 设 备 模 拟 或 上 下 文 管 理 的 大 多 数 函 数 ) 将 返<br />

cuCtxDetach() 来<br />

此 外 还 会 为 每 个 上 下 文 维 护 一 个 使 用 计 数<br />

文 。cuCtxAttach()<br />

下 文 与 宿 主 线 程 分 离 开 来 。 随 后 此 上 下 文 将 成 为 “ 浮 动 还 可 恢 复 之 前 的 当 前 上 下 文 ( 如 果 存 在 )。 上<br />

count)。cuCtxCreate()<br />

则 将<br />

主 线 程 的 当 前 上 下 文 。 如 果 有 效 上 下 文 未 成 为 线 程 的 当 前 上 下 文 , 在 一 个 上 下 文 中 操 作<br />

cuCtxDetach() 用 计 数 递 增 , 而 使 使<br />

回 <strong>CUDA</strong>_ERROR_INVALID_CONTEXT。<br />

使 之 递 减 。 在 调<br />

通 过 使 用 计<br />

上 下 文 压 入 堆 栈 顶 端 。 可 调 上 下 文 , 可 作 创 新<br />

的 <strong>CUDA</strong><br />

数 1<br />

数 ( 不<br />

建 一 个 上 下<br />

cuCtxCreate() 宿 主 线 程 一 次 只 能 有 一 个 当 前 设 备 上 下 文 。 在 使 用 个 一<br />

建 上 下 文 时 , 它 将 成 为 调 用 方 宿<br />

用 cuCtxDetach()<br />

使 用 计 数<br />

时<br />

客<br />

为 0<br />

用 相 同 的 上 下 文 , 则 每 个 库 都 将 调<br />

上 下 文 将 被 销 毁 。 ,<br />

用 计 数 促 进 了 在 同 一 上 下 文 中 操 作 第 三 授 权 代 码 之 间 的 互 操 作 。 举 例 来 说 , 如 果 载 入 了 三 个 库 使 递 减 使 用 计 数 。 对 于 大 多 数 来 说 , 应 用 程 序 将 在 载 入 或 初 始 化 库 之 前 创 建 一 个 上 下 文 , 通 过 这 种 方 式 , 应 用 程 序 即 可 使 用 自 己 的 启 发 式 方 法 来 创 建 上 下 文 , 库 只 需 在 传 递 给 它 的 上 下 文 中 操 作 即 可 。 使<br />

用 cuCtxAttach()<br />

来<br />

和<br />

如<br />

所<br />

递 增 使 用 计 数 , 并 在 库 不 再 使 用 该 上 下 文 时 调<br />

用<br />

希 望 创 建 自 己 的 上 下 文 的 库 (<br />

其 API<br />

户 端 并 不 了 解 这 种 情 况 , 并 且 可 能 已 经 创 建 或 未 创 建 自 己 的 上 下<br />

cuCtxPushCurrent() 可 使 用 ) 文<br />

cuCtxPopCurrent(),<br />

图 4-1<br />

。 示<br />

4.5.3.4 模 块 管 理<br />

图 4-1.<br />

库 上 下 文 管 理<br />

是<br />

CUmodule cuModule;<br />

cuModuleLoad(&cuModule, “myModule.cubin”);<br />

CUfunction cuFunction;<br />

作<br />

cuModuleGetFunction(&cuFunction, cuModule, “myKernel”);<br />

面 的 代 码 示 例 载 入 了 一 个 模 块 并 检 索 内 核 的 句 柄 : 下 。 操 互 行 进 中 文 下<br />

(module)<br />

4.5.3.5 执 行 控 制<br />

是<br />

参 见 第 4.2.5<br />

)。 所 有 符 号 的 名 称 ( 包 括 函 数 、 全 局 变 量 和 纹 理 参 考 ) 均 在 模 块 范 围 内 维 护 , 从 而 使 独<br />

模 块<br />

Windows 态 加 载 的 设 备 代 码 和 数 据 包 , 类 似 于 动 可<br />

的 DLL,<br />

由 nvcc<br />

出 的 ( 请<br />

cuFuncSetBlockShape() 为<br />

分 配 方 式 。 的<br />

<strong>CUDA</strong> 编<br />

31<br />

的 第 二 个 参 数 指 定 参 数 在 参 数 堆 栈 中 的 偏 移 。 这 个 偏 移 量 必 须 与 参 数 一 种 可 迁 移 的 方 式 来 完 成 此 任 务 数<br />

<strong>CUDA</strong> 第 三 方 编 写 的 模 块 可 在 相 同 的 的 立<br />

cuFuncSetSharedSize() 为<br />

cuParam*() 系<br />

数 设 置 共 享 存 储 器 的 大 小 。 函<br />

cuFuncSetBlockShape(cuFunction, blockWidth, blockHeight, 1);<br />

__alignof()<br />

参 数 。 类 型 的 对 齐 要 求 相 匹 配 。 可 通 过 使 用 的 供<br />

2.0 南 , 版 本 指 程<br />

threadID 函 数 设 置 每 个 块 的 线 程 数 , 同 时 还 会 设 置 其 定 给<br />

cuLaunch()<br />

各 cuParam*()<br />

cuLaunchGrid() 数 用 于 指 定 在 下 一 次 调 用 函 列<br />

启 动 内 核 时 为 内 核 提


中<br />

的<br />

个<br />

、cuMemAllocPitch() 分<br />

线 性 存 储 器 。 放<br />

节<br />

、<strong>CUDA</strong><br />

数<br />

int offset = 0;<br />

int i;<br />

cuParamSeti(cuFunction, offset, i);<br />

offset += sizeof(i);<br />

float f;<br />

cuParamSetf(cuFunction, offset, f);<br />

offset += sizeof(f);<br />

char data[32];<br />

cuParamSetv(cuFunction, offset, (void*)data, sizeof(data));<br />

offset += sizeof(data);<br />

cuParamSetSize(cuFunction, offset);<br />

cuFuncSetSharedSize(cuFunction, numElements * sizeof(float));<br />

cuLaunchGrid(cuFunction, gridWidth, gridHeight);<br />

4.5.3.6 存 储 器 管 理<br />

或<br />

分<br />

释<br />

CUdeviceptr devPtr;<br />

cuMemAlloc(&devPtr, 256 * sizeof(float));<br />

:<br />

// host code<br />

CUdeviceptr devPtr;<br />

int pitch;<br />

cuMemAllocPitch(&devPtr, &pitch,<br />

因<br />

浮 点 元 素 的 数 组<br />

width * sizeof(float), height, 4);<br />

cuModuleGetFunction(&cuFunction, cuModule, “myKernel”);<br />

cuFuncSetBlockShape(cuFunction, 512, 1, 1);<br />

cuParamSeti(cuFunction, 0, devPtr);<br />

cuParamSetSize(cuFunction, sizeof(devPtr));<br />

cuLaunchGrid(cuFunction, 100, 1);<br />

// device code<br />

__global__ void myKernel(float* devPtr)<br />

{<br />

for (int r = 0; r < height; ++r) {<br />

float* row = (float*)((char*)devPtr + r * pitch);<br />

for (int c = 0; c < width; ++c) {<br />

float element = row[c];<br />

}<br />

}<br />

}<br />

<strong>CUDA</strong> 数<br />

创<br />

销<br />

cuMemAlloc() 用 使 可<br />

cuMemAllocPitch()<br />

cuMemFree() 性 存 储 器 , 并 使 用 线 配<br />

256 的 代 码 示 例 在 线 性 存 储 器 中 分 配 了 一 个 包 含 面 下<br />

建 议 在 分 配 二 维 数 组 时 使<br />

用 cudaMallocPitch(),<br />

5.1.2.1 能 确 保 合 理 填 充 已 分 配 的 存 储 器 , 满 足 第 它 为<br />

绍 的 对 齐 要 求 , 从 而 确 保 访 问 行 地 址 或 执 行 二 维 数 组 与 设 备 存 储 器 的 其 他 区 域 之 间 的 复 制 ( 使 用<br />

cudaMemcpy2D()) 时 获 得 最 优 性 能 。 所 返 回 的 间 距 ( 或 步 幅 ) 必 须 用 于 访 问 数 组 元 素 。 以 下 代 码 示 例 将 分 介<br />

widthxheight 个 一 配<br />

维 浮 点 值 数 组 , 并 显 示 如 何 在 设 备 代 码 中 循 环 遍 历 数 组 元 素 : 二<br />

。 毁<br />

的<br />

数<br />

位<br />

浮 点 组 件 : 的<br />

<strong>CUDA</strong>_ARRAY_DESCRIPTOR desc;<br />

desc.Format = CU_AD_FORMAT_FLOAT;<br />

desc.NumChannels = 1;<br />

desc.Width = width;<br />

desc.Height = height;<br />

CUarray cuArray;<br />

cuArrayCreate(&cuArray, &desc);<br />

分<br />

组<br />

32 <strong>CUDA</strong> 编<br />

cuArrayCreate() 使 用 是 组<br />

cuArrayDestroy() , 使 用 的 建<br />

配 的 线 性 存 储 器<br />

widthxheight 代 码 示 例 分 配 了 一 个 下 以<br />

<strong>CUDA</strong><br />

32 包 含 一 个 , 组<br />

<strong>CUDA</strong>_MEMCPY2D copyParam;<br />

memset(&copyParam, 0, sizeof(copyParam));<br />

存 储 器 : 性 线 的 配<br />

copyParam.dstMemoryType = CU_MEMORYTYPE_ARRAY;<br />

copyParam.dstArray = cuArray;<br />

copyParam.srcMemoryType = CU_MEMORYTYPE_DEVICE;<br />

cuMemAlloc() 手 册 列 举 了 用 于 在 考 参<br />

2.0 南 , 版 本 指 程<br />

<strong>CUDA</strong> 之 间 复 制 存 储 器 的 所 有 函 数 。 下 面 的 代 码 示 例 将 二 维 数 组 复 制 到 之 前 代 码 示 例 中 分 配 的 组 数


。hostPtr<br />

copyParam.srcDevice = devPtr;<br />

copyParam.srcPitch = pitch;<br />

copyParam.WidthInBytes = width * sizeof(float);<br />

copyParam.Height = height;<br />

cuMemcpy2D(&copyParam);<br />

float data[256];<br />

int size = sizeof(data);<br />

CUdeviceptr devPtr;<br />

cuMemAlloc(&devPtr, size);<br />

cuMemcpyHtoD(devPtr, data, size);<br />

4.5.3.7 流 管 理<br />

面 的 代 码 示 例 将 一 些 宿 主 存 储 器 数 组 复 制 到 设 备 存 储 器 中 : 下<br />

CUstream stream[2];<br />

for (int i = 0; i < 2; ++i)<br />

cuStreamCreate(&stream[i], 0);<br />

for (int i = 0; i < 2; ++i)<br />

cuMemcpyHtoDAsync(inputDevPtr + i * size, hostPtr + i * size,<br />

size, stream[i]);<br />

for (int i = 0; i < 2; ++i) {<br />

cuFuncSetBlockShape(cuFunction, 512, 1, 1);<br />

int offset = 0;<br />

cuParamSeti(cuFunction, offset, outputDevPtr);<br />

offset += sizeof(int);<br />

cuParamSeti(cuFunction, offset, inputDevPtr);<br />

offset += sizeof(int);<br />

cuParamSeti(cuFunction, offset, size);<br />

offset += sizeof(int);<br />

cuParamSetSize(cuFunction, offset);<br />

cuLaunchGridAsync(cuFunction, 100, 1, stream[i]);<br />

面 的 代 码 示 例 创 建 了 两 个 流 : 这 些 流 均 通 过 以 下 代 码 示 例 定 义 为 一 个 任 务 序 列 , 包 括 一 次 从 宿 主 到 设 备 的 存 储 器 复 制 、 一 次 内 核 启 动 、 下<br />

次 从 设 备 到 宿 主 的 存 储 器 复 制 : 一<br />

}<br />

for (int i = 0; i < 2; ++i)<br />

cuMemcpyDtoHAsync(hostPtr + i * size, outputDevPtr + i * size,<br />

size, stream[i]);<br />

cudaCtxSynchronize();<br />

的<br />

数<br />

cuFunction<br />

允 处<br />

复<br />

必 的<br />

处 理 hostPtr<br />

许 一 个 流 的 存 储 器 复 制 与 另 外 一 个 流 的 内 核 执 行 相 互 重 叠<br />

须 指 向 分 页 锁 定 的 宿<br />

float* hostPtr;<br />

器 , 这 样 才 能 同 时 执 行 : 储 存 主<br />

cuMemAllocHost((void**)&hostPtr, 2 * size);<br />

hostPtr 流 均 会 将 其 输 入 数 组 个 两<br />

inputDevPtr 分 复 制 到 设 备 存 储 器 中 的 部 一<br />

中 , 通 过 调 用 组<br />

并<br />

设 备 上 的 inputDevPtr, 理<br />

outputDevPtr 果 结 将<br />

hostPtr 回 制<br />

相 同 部 分 。 使 用 两 个 流<br />

cuStreamSynchronize() 可<br />

4.5.3.8 事 件 管 理<br />

目<br />

事 件 管 理<br />

CUevent start, stop;<br />

cuEventCreate(&start);<br />

cuEventCreate(&stop);<br />

后 调 用 的 是 在 进 一 步 处 理 之 前 确 定 所 有 流 均 已 完 成 。 用 于 同 步 宿 主 与 特 定 流 , 允 许 其 他 流 继 续 在 该 设 备 上 执 行 。 最<br />

面 的 代 码 示 例 创 建 了 两 个 事 件 : 下<br />

<strong>CUDA</strong> 编<br />

33<br />

了 cuCtxSynchronize(),<br />

cuEventRecord(start, 0);<br />

for (int i = 0; i < 2; ++i)<br />

cuMemcpyHtoDAsync(inputDevPtr + i * size, hostPtr + i * size,<br />

些 事 件 可 用 于 为 上 一 节 的 代 码 示 例 计 时 , 方 法 如 下 : 这<br />

2.0 南 , 版 本 指 程


注 册 。 消<br />

包<br />

初<br />

的<br />

返<br />

或<br />

size, stream[i]);<br />

for (int i = 0; i < 2; ++i) {<br />

cuFuncSetBlockShape(cuFunction, 512, 1, 1);<br />

int offset = 0;<br />

cuParamSeti(cuFunction, offset, outputDevPtr);<br />

offset += sizeof(outputDevPtr);<br />

cuParamSeti(cuFunction, offset, inputDevPtr);<br />

offset += sizeof(inputDevPtr);<br />

cuParamSeti(cuFunction, offset, size);<br />

offset += sizeof(size);<br />

cuParamSetSize(cuFunction, offset);<br />

cuLaunchGridAsync(cuFunction, 100, 1, stream[i]);<br />

}<br />

for (int i = 0; i < 2; ++i)<br />

cuMemcpyDtoHAsync(hostPtr + i * size, outputDevPtr + i * size,<br />

size, stream[i]);<br />

cuEventRecord(stop, 0);<br />

cuEventSynchronize(stop);<br />

float elapsedTime;<br />

cuEventElapsedTime(&elapsedTime, start, stop);<br />

cuEventDestroy(start);<br />

cuEventDestroy(stop);<br />

4.5.3.9 纹 理 参 考 管 理<br />

cuTexRefSetArray() 将<br />

texture texRef;<br />

的<br />

CUtexref cuTexRef;<br />

cuModuleGetTexRef(&cuTexRef, cuModule, “texRef”);<br />

指 绑<br />

cuTexRefSetAddress() 核 使 用 纹 理 参 考 从 纹 理 存 储 器 中 读 取 之 前 , 必 须 使 用 内 在<br />

理 参 考 绑 定 到 纹 理 。 纹<br />

块 cuModule<br />

定 义 如 下 的 纹 理 参 考 texRef: 含<br />

如 果 模<br />

cuTexRefSetAddress(NULL, cuTexRef, devPtr, size);<br />

数 绑<br />

texRef 面 的 代 码 示 例 将 检 索 下 则<br />

柄 : 句<br />

cuTexRefSetArray(cuTexRef, cuArray, CU_TRSA_OVERRIDE_FORMAT);<br />

4.5.3.10 OpenGL 互 操 作 性<br />

texRef 的 代 码 示 例 将 面 下<br />

devPtr 到 定<br />

的 线 性 存 储 器 : 向<br />

texRef 的 代 码 示 例 将 面 下<br />

<strong>CUDA</strong> 到 定<br />

组 cuArray:<br />

考 手 册 列 举 了 用 于 设 置 寻 址 模 式 、 过 滤 模 式 和 其 他 针 对 纹 理 参 考 的 标 记 的 各 种 函 数 。 在 将 纹 理 绑 定 到 纹 理 参 考 时 所 指 定 的 格 式 必 须 与 声 明 纹 理 参 考 时 指 定 的 参 数 相 匹 配 ; 否 则 纹 理 拾 取 的 结 果 将 无 法 确 定 。 参<br />

GLuint bufferObj;<br />

cuGLRegisterBufferObject(bufferObj);<br />

GLuint bufferObj;<br />

CUdeviceptr devPtr;<br />

int size;<br />

cuGLMapBufferObject(&devPtr, &size, bufferObj);<br />

成 : 完<br />

除 映 射 是 通 解<br />

操 作 性 。 之 互<br />

完<br />

的 设 备 存 储 器 地 址 读 取 或 写 入 缓 冲 对 象 : 回<br />

取<br />

34 <strong>CUDA</strong> 编<br />

cuGLInit() 使 用 须 必<br />

OpenGL 与 化 始<br />

先 必 须 将 一 个 缓 冲 对 象 注 册 到 <strong>CUDA</strong>, 首<br />

cuGLRegisterBufferObject() 能 进 行 映 射 。 可 通 过 才 后<br />

cuGLMapBufferObject() 完 成 后 , 内 核 即 可 使 用 册 注<br />

cuGLUnregisterBufferObject() , 可 使 用 的 成<br />

2.0 南 , 版 本 指 程<br />

过 cuGLUnmapBufferObject()


创<br />

填<br />

程 指 南 , 版<br />

上 上<br />

将<br />

资<br />

设<br />

用<br />

为<br />

4.5.3.11 Direct3D 互 操 作 性<br />

Direct3D 互<br />

LPDIRECT3DVERTEXBUFFER9 buffer;<br />

cuD3D9RegisterResource(buffer, CU_D3D9_REGISTER_FLAGS_NONE);<br />

LPDIRECT3DSURFACE9 surface;<br />

cuD3D9RegisterResource(surface, CU_D3D9_REGISTER_FLAGS_NONE);<br />

cuD3D9RegisterResource()<br />

cuD3D9UnregisterVertexBuffer() 可 可<br />

<strong>CUDA</strong> 性 要 求 在 创 建 作 操<br />

Direct3D 时 指 定 文 下<br />

cuD3D9CtxCreate() 通 过 使 用 。 备<br />

cuCtxCreate() 非 而<br />

建 <strong>CUDA</strong><br />

下 文 即 可 实 现 此 目 标 。。<br />

cuD3D9UnmapResources()<br />

有 较 高 的 开 销 , 通 常 仅 为 每 个 资 源 调 用 一 次 。 使 取 消 注 册 。 之 和 任 意 多 次 地 映 射 和 解 除 映 射 。 内 核 可 使 用 具 能<br />

cuD3D9ResourceGetMappedPointer()<br />

cuD3D9ResourceGetMappedSize()、cuD3D9ResourceGetMappedPitch()<br />

cuD3D9ResourceGetMappedPitchSlice() 返 访 及 返<br />

cuD3D9RegisterResource() 即 可 使 用 后 随<br />

Direct3D<br />

注 册 到 <strong>CUDA</strong>: 源<br />

0<br />

CUdeviceptr devPtr;<br />

cuD3D9ResourceGetMappedPointer(&devPtr, buffer);<br />

size_t size;<br />

cuD3D9ResourceGetMappedSize(&size, buffer);<br />

cuMemset(devPtr, 0, size);<br />

用<br />

height) 的<br />

设 备 存 储 器 地 址 和 回 的 大 小 和 间 距 信 息 来 读 取 和 写 入 已 映 射 的 资 源 。 通 问 已 映 射 的 资 源 将 导 致 不 确 定 的 结 果 。 回<br />

面 的 代 码 示 例 使 充 了 一 个 缓 冲 区 : 下<br />

<strong>CUDA</strong> 源 注 册 到 资 将<br />

cuD3D9MapResources() 即 可 在 需 要 时 分 别 使 用 , 后<br />

// host code<br />

代 码 示 例 中 , 每 个 线 程 都 访 问 大 小 的 面 下 在<br />

CUdeviceptr devPtr;<br />

cuD3D9ResourceGetMappedPointer(&devPtr, surface);<br />

size_t pitch;<br />

cuD3D9ResourceGetMappedPitch(&pitch, surface);<br />

cuModuleGetFunction(&cuFunction, cuModule, “myKernel”);<br />

cuFuncSetBlockShape(cuFunction, 16, 16, 1);<br />

int offset = 0;<br />

cuParamSeti(cuFunction, offset, devPtr);<br />

offset += sizeof(devPtr);<br />

cuParamSeti(cuFunction, 0, width);<br />

offset += sizeof(width);<br />

cuParamSeti(cuFunction, 0, height);<br />

offset += sizeof(height);<br />

cuParamSeti(cuFunction, 0, pitch);<br />

offset += sizeof(pitch);<br />

cuParamSetSize(cuFunction, offset);<br />

cuLaunchGrid(cuFunction,<br />

(width+Db.x–1)/Db.x, (height+Db.y–1)/Db.y);<br />

// device code<br />

__global__ void myKernel(unsigned char* surface,<br />

int width, int height, size_t pitch)<br />

{<br />

int x = blockIdx.x * blockDim.x + threadIdx.x;<br />

int y = blockIdx.y * blockDim.y + threadIdx.y;<br />

if (x >= width || y >= height) return;<br />

float* pixel = (float*)(surface + y * pitch) + 4 * x;<br />

}<br />

二 维 表 面 的 一 个 像 素 , 像 素 格 式<br />

过 Direct3D<br />

为 (width,<br />

float4:<br />

<strong>CUDA</strong> 编<br />

35<br />

本 2.0


,(i/n) 等<br />

和<br />

块<br />

块<br />

位 个<br />

个<br />

。<br />

而<br />

;:<br />

节<br />

、__logf(x)(<br />

等<br />

(arithmetic<br />

和<br />

节<br />

,__[u]mul24 将<br />

个<br />

位 位<br />

是<br />

个<br />

个<br />

第 5 章 性 能 指 南<br />

5.1 指 令 性 能<br />

<br />

<br />

<br />

执 读<br />

行 指 令 ; 块<br />

为<br />

块<br />

理 指 令 , 多 处 理 器 必 须 中 各 线 程 的 指 令 操 作 数 处<br />

中 各 线 程 写 入 结 果<br />

最 量<br />

<br />

允 最<br />

warp<br />

<br />

节<br />

intensity), 也<br />

warp 线 程 为 要<br />

许 线 程 调 度 程 序 尽 可 能 地 同 时 进 行 存 储 器 事 务 处 理 与 数 学 计 算 , 这 要 求<br />

取 warp<br />

而 , 有 效 的 指 令 吞 吐 量 取 决 于 额 定 指 令 吞 吐 量 以 及 存 储 器 延 迟 和 带 宽 。 可 通 过 以 下 方 法 最 大 化 指 令 吞 吐<br />

<br />

因<br />

每<br />

5.1.1 指 令 吞 吐 量<br />

小 化 吞 吐 量 较 低 的 指 令 的 使 用 ( 参 见 :<br />

);<br />

5.1.1<br />

线 程 执 行 的 程 序 具 有 较 高 的 运 算 强 度 第<br />

数 学 操 作 ; 量<br />

5.1.1.1 数 学 指 令<br />

就 是 说 , 让 每 个 存 储 器 操 作 对 应 大 :<br />

5.1.2 用 于 每 一 类 存 储 器 的 可 用 存 储 器 带 宽 的 使 用 ( 参 见 第 化 大<br />

);<br />

4<br />

<br />

<br />

<br />

16<br />

位 32<br />

单 整 位 个<br />

加<br />

节<br />

5.2 处 理 器 上 具 有 多 个 活 动 线 程 , 如 第 多 个<br />

述 。 所<br />

钟 周 期 , 用 于 : 型 加 法 ; 运 算 、 比 较 、 最 小 值 、 最 大 值 、 类 型 转 换 指 令 ; 时<br />

供 有 符 号 和 无 符 号 24<br />

整 型 乘 法 。 而 在 未 来 的 架 构 中<br />

型 乘 法 的 速 度 更 慢 , 因 整 型 乘 法 , 由 应 用 程 序 合 理 整<br />

warp 一 个 为 要<br />

出 一 条 指 令 , 多 处 理 器 需 占 用 : 发<br />

- 浮 点 加 法 、 乘 法 和 乘 度 精<br />

;<br />

另<br />

是<br />

的<br />

)。 请 参 见 附 录 B) 可 请<br />

时 钟 周 期 内 提<br />

这 些 转 换 。<br />

36 <strong>CUDA</strong> 编<br />

时 钟 周 期 ,<br />

时 钟 周 期 , 用 于 倒 数 、 平 方 根 倒 数<br />

B.2 第 见 参<br />

。<br />

16 乘 法 占 用 型 整<br />

但 __mul24<br />

__umul24(<br />

2<br />

在 4<br />

y) 提 块<br />

比 32<br />

我 们 建 议 您 设 计 两 套 内 核 , 一 个 使 用 __[u]mul24, 此<br />

32 使 用 普 通 的 个 一<br />

__sinf(x)、__cosf(x)、__expf(x) 占 B)。 录<br />

个<br />

。sinf(x)、cosf(x)、tanf(x)、sincosf(x)<br />

用 整 型 除 法 和 求 模 运 算 的 成 本 极 高 , 应 尽 可 能 避 免 使 用 , 或 在 可 能 的 情 况 下 替 换 为 位 运 算 : 如 如 调<br />

果 n<br />

他 函 数 要 占 用 更 多 的 时 钟 周 期 , 因 为 它 们 是 作 为 多 种 指 令 的 混 合 体 实 现 的 。 单 精 度 浮 点 平 方 根 是 作 为 倒 数 平 方 根 再 求 倒 数 实 现 的 , 而 非 先 求 倒 数 平 方 根 再 求 乘 积 , 因 为 只 有 这 样 才 能 其<br />

期 ( 请 参 见 附 周<br />

于 (i>>log2(n)), 价<br />

(i%n)<br />

于 (i&(n-1)); 价<br />

果 n<br />

常 量 , 则 编 译 器 将 执 行<br />

幂<br />

36 度 浮 点 除 法 要 占 用 精 单<br />

__fdividef(x, 周 期 , 但 钟 时<br />

20 速 度 更 快 的 版 本 , 只 需 占 用 了 供<br />

时 钟<br />

2.0 南 , 版 本 指 程<br />

为 0<br />

warp 大 给 出 正 确 结 果 。 因 而 , 一 个 穷 无<br />

32 用 占 将<br />

钟 周 期 。 时<br />

用 32<br />

时 钟 周 期


块<br />

器 延 迟 。<br />

的<br />

(if、switch、do、for、while)<br />

的<br />

为<br />

块<br />

块<br />

谓<br />

了<br />

、4<br />

块<br />

是<br />

节<br />

块<br />

块<br />

果 x<br />

对 值 大 于 48039( 绝<br />

见 math_functions.h<br />

5.1.2.2 低 性 能 , 因 为 本 地 存 储 器 的 延 迟 较 高 , 也 存 在 带 宽 问 题 ( 请 参 见 第 降 步<br />

)。<br />

<br />

<br />

单 节 可 通 过 以 下 方 法 避 免 上 述 的 后 两 种 情 况 : 双<br />

成 本 更 高 , 如 参 解 更 多 细 节 ), 则 成 本 还 要 更 高 ( 也 就 是 说 , 速 度 降 低 约 一 个 数 量 级 )。 此 外 , 在 这 种 情 况 下 , 参 数 约 减 代 码 使 用 本 地 存 储 器 , 这 可 能 会 进 一 有 些 时 候 , 编 译 器 必 须 插 入 转 换 指 令 , 这 又 带 来 了 额 外 的 执 行 周 期 。 可 能 导 致 此 类 情 况 的 条 件 包 括 : 的<br />

类 精 度 浮 点 常 量 ( 定 义 时 不 带 任 何 类 型 后 缀 ) 用 作 单 精 度 浮 点 计 算 的 输 入 ; 或<br />

<br />

<br />

5.1.1.2 控 制 流 指 令<br />

力 能 算 计 如<br />

后 类 或 更 低 的 设 备 , 应 将 双 精 度 算 法 替 换 为 单 精 度 算 法 。 后<br />

控 制 流 指 令<br />

对 char<br />

short<br />

进 行 操 作 的 函 数 , 其 操 作 数 通 常 需 要 转 换 为 int; 型<br />

B.1.2 浮 点 变 量 用 作 度 精<br />

定 义 的 数 学 函 数 的 双 精 度 版 本 的 输 入 参 数 。 所<br />

的 线 程 分 支 , 从 而 显 著 影 响 有 效 的<br />

型 和 单 精 度 数 学 函 数 。 在 为 不 具 备 本 地 双 精 度 支 持 的 设 备 编 译 时 ,<br />

f 单 精 度 浮 点 常 量 , 在 定 义 时 带 用 使<br />

, 如 3.141592653589793f、1.0f、0.5f; 缀<br />

/ WSIZE) 时 块 块<br />

节<br />

f 数 学 函 数 的 单 精 度 版 本 , 定 义 时 同 样 带 用 使<br />

, 如 sinf()、logf()、expf()。 缀<br />

float 单 精 度 代 码 , 强 烈 建 议 使 用 于 对<br />

为 1.2<br />

任 何 流 控 制 指 令<br />

warp 致 同 一 导 会<br />

节<br />

块<br />

(branch<br />

unroll<br />

或 语 指 来 predication)<br />

令 吞 吐 量 , 也 就 是 说 , 这 些 指 令 会 导 致 线 程 采 用 不 同 的 执 行 路 径 。 如 果 出 现 这 种 情 况 , 就 必 须 序 列 化<br />

(serialize) 不 将 重 新 汇 聚 到 同 一 执 行 路 径 。 指<br />

warp 执 行 路 径 , 因 而 增 加 了 该 的 同<br />

执 行 的 指 令 总 数 。 完 成 所 有 不 同 的 执 行 路 径 时 , 线 程<br />

都<br />

ID 在 控 制 流 以 线 程 了 为<br />

warp 的 情 况 下 获 得 最 佳 性 能 , 应 编 写 控 制 条 件 , 最 小 化 分 支 据 依<br />

的 数 量 。<br />

warp 完 全 可 行 的 , 因 为 是 这<br />

3.1 内 的 分 布 情 况 是 确 定 的 , 如 块 在<br />

所 述 。 以 一 个 简 单 的 情 况 为 例 , 当<br />

或<br />

的<br />

(threadIdx 条 件 仅 依 赖 于 制 控<br />

WSIZE 如 此 , 其 中 的 是 就<br />

warp<br />

的 大 小 。 此 时 不 会 出 现 任<br />

在 使 用 转 移 猜 测 时 , 依 靠 控 制 条 件 执 行 的 任 何 指 令 都 不 会 被 跳 过 。 而 是 分 别 与 一 个 每 线 程 条 件 代 码 或 根 据<br />

何 warp<br />

warp , 因 为 控 制 条 件 与 支 分<br />

美 对 齐 。 完<br />

相 (predicate)<br />

5.1.1.3 存 储 器 指 令<br />

有 些 时 候 , 控 制 器 可 能 会 展 开 循 环 , 或 通 过 使 用 转 移 猜 测<br />

if 化 优<br />

switch<br />

句 ,<br />

warp 将 加 以 介 绍 。 在 这 些 情 况 下 , 不 会 有 任 何 文 下<br />

#pragma 。 程 序 员 还 可 使 用 支 分<br />

令 控 制 循<br />

4.2.5.2 展 开 ( 请 参 见 第 的 环<br />

)。<br />

warp<br />

。 只 有 在 分 支 条 件 控 制 的 指 令 数 量 小 于 或 等 于 特 定 阈 值 时 , 编 译 器 才 会 使 用 猜 测 的 指 令 替 换 分 支 指 令 : 如 果 编 译 确 定 出 有 可 能 产 生 大 量 分 支 的 条 件 , 则 此 阈 值 为 7, 否 则 为 4。 作 数<br />

器 指 令 包 含 读 取 或 写 入 共 享 、 本 地 或 全 局 存 储 器 的 任 何 指 令 。 只 有 在 使 用 某 些 自 动 变 量 时 才 会 发 生 本 节 储 存<br />

到<br />

个<br />

个<br />

块<br />

true 条 件 设 置 为 制 控<br />

false<br />

谓 词<br />

关 联 , 尽 管 每 一 条 指 令 都 为 执 行 而 进 行 了 调 度 , 但 只<br />

true 词 为 谓 有<br />

false 才 会 被 实 际 执 行 。 带 有 令 指<br />

词 的 指 令 不 会 写 入 结 果 , 也 不 会 计 算 地 址 或 读 取 操<br />

__shared__ float shared[32];<br />

__device__ float device[32];<br />

shared[threadIdx.x] = device[threadIdx.x];<br />

个 个<br />

到<br />

个<br />

<strong>CUDA</strong> 编<br />

37<br />

果 在 等 待 全 局 存 储 器 访 问 完 成 时 有 足 够 的 独 立 算 数 指 令 可 发 出 , 则 线 程 调 度 程 序 可 隐 藏 这 样 的 全 局 存 储 如<br />

例 说 明 , 注 意 以 下 示 例 代 码 中 的 赋 值 运 算 符 : 举<br />

4.2.2.4 储 器 访 问 , 详 见 第 存 地<br />

。<br />

4 理 器 要 占 用 处 多<br />

warp 周 期 来 为 一 个 钟 时<br />

发 出 一 条 存 储 器 指 令 。 在 访 问 本 地 或 全 局 存 储 器 时 , 还<br />

400 额 外 的 在 存<br />

600<br />

钟 周 期 的 存 储 器 延 迟 。 时<br />

4 占 用 将 它<br />

时 钟 周 期 来 发 送 全 局 存 储 器 的 读 取 指 令<br />

时 钟 周 期 来 发 送 共 享 存 储 器 的 写 入 指 令 , 但<br />

2.0 南 , 版 本 指 程<br />

400 需 要 共 总<br />

600<br />

钟 周 期 来 从 全 局 存 储 器 读 取 一 个 浮 点 数 。 时


个<br />

,type<br />

位<br />

、64 位<br />

个<br />

或<br />

条<br />

位<br />

的<br />

位<br />

块<br />

出 指 令 。 发<br />

5.1.1.4 同 步 指 令<br />

,__syncthreads 将<br />

5.1.2 存 储 器 带 宽<br />

程 需 要 等 待 其 他 线 程 线 何 任 有 没 果 如<br />

存 储 器 带 宽<br />

<br />

<br />

<br />

<br />

<br />

若 在 与 将<br />

存 储 器 空 间 的 有 效 带 宽 主 要 取 决 于 访 问 模 式 下 面 几 节 将 介 绍 相 关 内 容 由 于 设 备 存 储 器 比 片 上 存 储 器 的 延 迟 更 高 、 带 宽 更 低 , 因 此 应 尽 量 减 少 设 备 存 储 器 访 问 。 典 型 的 编 程 模 式 是 将 来 自 设 备 存 储 器 的 数 据 转 入 共 享 存 储 器 , 也 就 是 说 , 使 一 个 块 的 所 有 线 程 各<br />

自 设 备 存 储 器 的 载 入 共 享 存 储 器 共 享 存 储 器 中 处 理 数 据 ; 来<br />

4 用 占<br />

warp 周 期 来 为 一 个 钟 时<br />

5.1.2.1 全 局 存 储 器<br />

:。<br />

块 中 的 其 他 所 有 线 程 同 步 , 使 各 线 程 可 安 全 地 读 取 由 其 他 线 程 写 入 的 共 享 存 储 器 位 置 ; 有 必 要 , 再 次 进 行 同 步 , 确 保 使 用 结 果 更 新 了 共 享 存 储 器 ; ;<br />

值 : 赋<br />

果 写 回 设 备 存 储 器 。 结<br />

__device__ type device[32];<br />

问 的 高 昂 成 本 时 更 是 如 此 。 访 器 储 存<br />

type data = device[tid];<br />

sizeof(type) 字 必<br />

的 等<br />

的<br />

全 局 存 储 器 空 间 不 会 被 缓 存 , 因 而 采 用 正 确 的 访 问 模 式 来 实 现 最 大 化 的 存 储 器 带 宽 尤 为 重 要 , 考 虑 到 设 备<br />

节<br />

或<br />

32 , 设 备 能 够 通 过 一 条 指 令 将 全 局 存 储 器 中 的 先 首<br />

或 128<br />

读 入 寄 存 器 。 对 于 下 面 这 样 的<br />

类<br />

或<br />

来<br />

struct __align__(8) {<br />

float a;<br />

float b;<br />

};<br />

对<br />

将 其 编 译 为 一 条 加 载 指 令<br />

sizeof(type) 使 须<br />

于 4、8<br />

16,<br />

type 为 型<br />

量 必 须 与 变<br />

sizeof(type) 致 ( 也 就 是 说 , 它 的 地 址 必 须 是 一 节<br />

倍 数 )。<br />

齐 要 求 , 举 例 如 下 :<br />

struct __align__(16) {<br />

对<br />

};<br />

float a;<br />

float b;<br />

float c;<br />

个<br />

4.3.1.1 于 对<br />

float2 的 内 置 类 型 , 如 绍 介<br />

float4,<br />

要 求 可 自 动 满 足 。 齐<br />

__align__(8) 结 构 体 来 说 , 可 通 过 使 用 对 齐 说 明 符 于 对<br />

__align__(16)<br />

使 编 译 器 实 施 大 小 和<br />

节 的 结 构 体 来 说 , 编 译 器 会 生 成 多 条 加 载 指 令 。 为 了 确 保 生 成 的 指 令 数 量 最 少 , 应 使 用 字<br />

__align__(16)<br />

struct __align__(16) {<br />

float a;<br />

float b;<br />

float c;<br />

float d;<br />

float e;<br />

};<br />

定<br />

: 或<br />

于 超 对<br />

条<br />

此 类 结 构 体 , 举 例 如 下 义<br />

位<br />

38 <strong>CUDA</strong> 编<br />

过 16<br />

加 载 指 令 , 而 的 加 载 指 令 。 位 于 全 局 存 储 器 中 的 变 量 的 地 址 , 或 由 驱 动 程 序 或 运 行 存 储 器 分 配 例 程 返 回 的 变 量 地 址 总 是 会 字 节 。<br />

:<br />

2 编 译 为 将 这<br />

非 5<br />

2.0 南 , 版 本 指 程<br />

256 到 至 少 齐 对<br />

时 API<br />

128<br />

32


warp , 当 半 块 中 的 线 程 同 时 进 行 的 存 储 器 访 问 ( 在 单 独 一 条 读 取 或 写 入 指 令 执 行 的 过 程 中 ) 可 合 并 一 个 存 储 器 事 务 , 全 局 存 储 器 带 宽 的 使 用 效 率 将 达 到 最 高 。 存 储 器 次 其<br />

(memory transaction)<br />

32 1.2 )、64 128<br />

warp<br />

大 小 可 为 字 节 ( 仅 针 对 为 或 更 高 设 备 位 或 位 本 节 的 后 续 内 容 将 介 绍 根 据 设 备 的 计 算 能 力 合 并 存 储 器 访 问 的 各 种 需 求 。 如 果 半 务 事 时 (coalesce)<br />

warp<br />

能 够 满 足 这 些 需 求 , 即 便 在 块 分 支 、 块 的 某 些 线 程 并 未 实 际 访 问 存 储 器 的 情 况 下 , 也 可 实 现 合 并 。 。<br />

下 面 的 讨 论 中 , 全 局 存 储 器 将 被 视 为 分 区 成 大 小 等 或 字 节 的 部 分 , 并 且 对 齐 到 此 大 小 。 块 在<br />

warp<br />

warp<br />

半<br />

满 足 以 下 三 个 条 件 , 半 的 线 程 必 须 访 问 果 如<br />

在 计 算 能 力 为 1.0 和 1.1 的 设 备 上 进 行 存 储 器 合 并<br />

<br />

<br />

32、64 128 于<br />

32 64<br />

64 128<br />

128 128<br />

储 器 访 问 都 会 合 并 为 一 个 或 两 个 存 储 器 事 务 : 位 , 得 到 一 个 字 节 的 存 储 器 事 务 ,<br />

一 , 所 有<br />

16<br />

线<br />

128<br />

程 进 行 的 全 局 存<br />

存 储 器 事 务 ; 全 部 个 字 必 须 位 于 大 小 等 于 存 储 器 事 务 大 小 的 同 一 个 存 储 器 段 (segment) 中 ( 在 访 问 位 字 的 情 况 下 , 位 于 存 储 器 事 务 大 小 两 倍 的 分 段 中 ); 的 节 字 个 两 到 得 , 字 或 必 须 按 顺 序 访 问 字 : 块 中 的 个 线 程 必 须 访 问 个 字 。 如 果 块 不 满 足 上 述 所 有 需 求 , 将 为 各 线 程 发 出 一 个 独 立 的 存 储 器 事 务 , 而 吞 吐 量 将 显 著 降 低 。 显 示 了 接 合 后 的 存 储 器 访 问 的 示 例 , 而 和 显 示 了 未 为 计 算 能 力 或 的 设 备 进 行 存 储 器 合 并 的 存 储 器 访 问 示 例 。 程<br />

线<br />

warp k k<br />

warp<br />

5-1 5-2 5-3 1.0 1.1<br />

第<br />

64<br />

第<br />

32 128<br />

32 32<br />

64 4 ,128<br />

半<br />

2<br />

半<br />

的 位 访 问 带 宽 比 存 储 器 合 并 后 的 位 访 问 相 比 略 低 而 存 储 器 合 并 后 的 位 访 问 则 位 访 问 带 宽 低 出 许 多 。 然 而 , 同 为 位 访 存 时 , 尽 管 未 存 储 器 合 并 的 访 问 的 带 图 图 图 是<br />

器 合 并 后 的 访 问 带 宽 要 低 一 个 数 量 级 , 但 同 为 位 情 况 下 , 前 者 带 宽 比 后 者 低 倍 位 情 况 下 , 前 者 带 宽 比 后 者 低 倍 。 后 并 储 存 比 宽 合 器 储 存<br />

在 计 算 能 力 为 1.2 或 更 高 的 设 备 上 进 行 存 储 器 合 并<br />

warp 所 有 半 块 的 所 有 线 程 访 问 的 字 位 于 大 小 满 足 以 下 条 件 的 同 一 个 存 储 器 段 内 , 所 有 线 程 进 行 的 全 局 存 储 器 访 问 都 会 合 并 为 一 个 或 两 个 存 储 器 事 务 : 要 只<br />

<br />

<br />

如 块<br />

块<br />

位 字 8 32<br />

16 64<br />

32 64 128<br />

warp warp n n 字 , 则 为 节 ;<br />

n 1 16 128<br />

果 所 有 线 程 都 访 问 或 字 , 则 为 节 。 半 所 请 求 的 任 何 地 址 模 式 都 会 实 现 存 储 器 合 并 包 括 多 个 线 程 同 一 个 地 址 的 模 式 。 这 与 具 有<br />

能 力 的 设 备 的 情 况 截 然 不 同 , 在 那 种 情 况 下 , 线 程 需 要 串 行 地 访 问 字 。<br />

128 64<br />

如 果 半 在 不 同 的 存 储 器 段 内 对 字 进 行 寻 址 , 则 发 出 存 储 器 事 务 ( 每 个 事 务 针 对 一 个 存 储 器 段 ), 而 计 算 能 力 较 低 的 设 备 将 在 于 发 出 事 务 。 具 体 来 说 , 如 果 线 程 访 问 , 则 至 少 发 出 两 个 存 储 器 事 务 。<br />

warp<br />

较 低 计 算<br />

事 务 中 , 无 用 字 也 会 被 读 取 , 这 将 浪 费 带 宽 。 为 减 少 浪 费 , 硬 件 将 自 动 发 出 包 含 所 请 求 的 字 的<br />

8 32<br />

最 小 的 存 储 器 事 务 。 举 例 来 说 , 如 果 全 部 字 都 位 于 一 个 字 节 分 区 的 一 半 , 则 发 出 一 个 位<br />

16 64 32 、64 128 128<br />

的 事 务 。<br />

<br />

<br />

更 精 确 地 来 说 , 以 下 协 议 用 于 为 半 块 发 出 存 储 器 事 务 : 在<br />

<br />

存<br />

128<br />

储<br />

64<br />

器<br />

编 号 最 的 活 动 线 程 所 请 求 地 址 的 存 储 器 段 。 对 于 位 数 据 来 说 , 段 大 小 是 字 节 , 对 于 数 据 是 字 节 , 对 于 位 位 和 位 数 据 是 字 节 。<br />

<strong>CUDA</strong> 2.0 39<br />

求 位 于 同 一 存 储 器 段 内 的 地 址 的 其 他 所 有 活 动 线 程 。 尽 可 能 减 小 事 务 的 大 小 :<br />

包 含<br />

大 小 为 字 节 , 而 且 仅 使 用 了 下 半 或 上 半 , 则 将 事 务 大 小 缩 减 为 字 节 ; 务 事 果 如 请 找 查<br />

本 版 , 南 指 程 编<br />

个<br />

位<br />

大<br />

时<br />

字<br />

个<br />

个<br />


字<br />

存<br />

存<br />

或 块<br />

(inactive)。<br />

。<br />

。<br />

得 到 一 个 存 储 器 事 务 。<br />

存 储 器 合 并 后 的 存 储 器 访 问 模 式 示 例 。<br />

字<br />

。 节<br />

<br />

重<br />

如<br />

展<br />

64 务 大 小 为 事 果<br />

32 而 且 仅 使 用 了 下 半 或 上 半 , 则 将 事 务 大 小 缩 减 为 , 节<br />

执 行 事 务 , 并 将 得 到 服 务 的 线 程 标 记 为 不 活 动<br />

1.2 计 算 能 力 为 了 示<br />

更 高 的 设 备 的 全 局 存 储 器 访 问 示 例<br />

warp 述 操 作 , 直 至 为 半 上 复<br />

中 的 所 有 线 程 提 供 了 服 务<br />

图 5-4<br />

储 器 访 问 , 得 到 一 个 存 储 器 事 务<br />

40 <strong>CUDA</strong> 编<br />

float : 存 储 器 合 并 后 的 侧 左<br />

float : 存 储 器 合 并 后 的 侧 右<br />

器 访 问 ( 分 支 warp), 储<br />

图 5-1.<br />

2.0 南 , 版 本 指 程


存<br />

未 为 计<br />

程 指 南 , 版<br />

个<br />

个<br />

或<br />

务<br />

的 设 备 进 行 存 储 器 合 并 的 全 局 存 储 器 访 问 模 式 示 例 。<br />

储 器 事 务 存 储 器 事 存<br />

<strong>CUDA</strong> 编<br />

41<br />

float : 非 连 续 的 侧 左<br />

16 访 问 , 得 到 器 储<br />

16 : 使 用 未 对 齐 的 起 始 地 址 , 得 到 侧 右<br />

图 5-2.<br />

为 计 是 算 能 力 未<br />

是 1.0<br />

1.1<br />

本 2.0


存<br />

存<br />

未<br />

个<br />

或<br />

个<br />

。<br />

的 设 备 进 行 存 储 器 合 并 的 全 局 存 储 器 访 问 模 式 示 例<br />

存 储 器 事 务 42 <strong>CUDA</strong> 编<br />

float : 不 相 邻 的 侧 左<br />

16 访 问 , 得 到 器 储<br />

float3 : 不 相 邻 的 侧 右<br />

16 访 问 , 得 到 器 储<br />

图 5-3.<br />

是 未 为 计 算 能 力 是 1.0<br />

1.1<br />

2.0 南 , 版 本 指 程


字<br />

字<br />

存<br />

存<br />

,type<br />

计<br />

(Common<br />

南 , 版 指 程<br />

存<br />

或<br />

类<br />

为<br />

的<br />

。<br />

是<br />

节 的 存 储 器 段 内 的 随<br />

一 般 访 问 模 式<br />

间 右 侧 : 未 对 齐 中<br />

<strong>CUDA</strong> 编<br />

type*<br />

43<br />

组 存 储 于 存 储 器 之 中 , 而 不 是 单 独 一 个 型 的 数 组 。 数 个<br />

64 : 在 一 个 侧 左<br />

float<br />

Access<br />

机<br />

是 处<br />

Pattern)<br />

一 个 数 组 的 一 个 元 素 : 的<br />

每 个 线 程 使 用 以 下 地 址 访<br />

储 器 访 问 , 得 到 一 个 存 储 器 事 务<br />

的 float<br />

的 float<br />

图 5-4.<br />

为 计 算 能 力 为 1.2<br />

或 更 高 的 设 备 的 全 局 存 储 器 访 问 示 例<br />

BaseAddress + tid<br />

必<br />

器 访 问 , 得 到 一 个 事 务 。 储<br />

器 访 问 , 得 到 两 个 事 务 。 储<br />

局 存 储 器 的 一 般 访 问 模 式 全<br />

为 了 实 现 存 储 器 合 并<br />

须 满 足 上 文 介 绍 的 大 小 和 对 齐 要 求 。 具 体 来 说 , 这 也 就 意 味 着 , 如<br />

问 类 型 为 type*、<br />

位<br />

本 2.0<br />

ID 线 程 : 指<br />

tid<br />

BaseAddress 址 地 于<br />

果 type<br />

16 大 于 个 一<br />

节 的 结 构 体 , 就 应 将 其 分 割 为 多 个 满 足 这 些 需 求 的 结 构 体 , 而 数 据 应 作 为 此 类 结 构 体 的 多


(local<br />

(padding),<br />

块<br />

块<br />

是<br />

的<br />

块<br />

节<br />

个<br />

块<br />

:<br />

倍 个<br />

块<br />

的<br />

块<br />

(bank 访 conflict),<br />

(bank),<br />

址<br />

和<br />

块<br />

路<br />

BaseAddress 处<br />

的<br />

BaseAddress + width * ty + tx<br />

ty) 的<br />

<br />

Width<br />

线<br />

(tx, 一 种 全 局 存 储 器 一 般 访 问 模 式 是 索 引 为 外 另<br />

于 地<br />

cuMemAllocPitch() 函<br />

5.1.2.2 本 地 存 储 器<br />

维 数 组 中 的 一 个 元 素 大 小 的 倍 数 ; 二<br />

数 。<br />

么 对 于 该 数 组 的 访 问 就 越 有 效 率 。 参 考 手 册 中 介 绍 倍<br />

memory) 访<br />

应 的 填 充 那 数 和 相 关 的 存 储 器 复 制 函 数 使 程 序 员 能 够 编 写 不 依 赖 于 硬 件 的 代 码 , 以 分 配 符 合 这 些 限 制 条 件 的 数 组 。 相<br />

节<br />

实 现 存 储 器 合 并 : 位<br />

数 , 并 且 行 得 到 了 倍<br />

线 程 使 用 以 下 地 址 访 问 类 型 为 type*、 各<br />

width 度 为 宽 、<br />

warp 种 情 况 下 , 只 有 满 足 了 以 下 条 件 , 才 能 为 线 程 块 的 所 有 半 这 在<br />

warp 的 宽 度 是 半 块 程<br />

16<br />

16 来 说 , 这 也 就 意 味 着 , 宽 度 不 是 体 具<br />

16 的 数 组 在 分 配 时 的 宽 度 越 接 近 数 倍<br />

所 述 与 全 局 存 储 器 空 间 相 似 , 本 地 存 储 器 空 间 不 会 被 缓 存 , 因 此 本 地 存 储 器 的 访 问 成 本 与 全 局 存 储 器 一 样 高 。 但 由 于 它 们 在 定 义 上 是 基<br />

的 cudaMallocPitch()<br />

5.1.2.3 常 量 存 储 器<br />

4.2.2.4 由 某 些 自 动 变 量 分 配 , 如 第 仅 问<br />

每 个 线 程 的 , 因 而 访 问 总 是 会 合 并 。 于 存 储 器 空 间 会 被 缓 存 , 因 此 常 量 存 储 器 的 读 取 仅 需 在 缓 存 丢 失 时 读 取 一 次 设 备 存 储 器 , 否 则 只 需 读 取 常 量 缓 存 即 可 。<br />

warp<br />

warp<br />

度 一 样 快 。 成 本 随 着 所 有 线 程 读 取 的 不 同 地 址 的 数 量 增 加 而 线 性 增 加 。 我 们 建 议 , 使 整 个 的 所 有 线 程 都 读 取 相 同 的 地 址 , 而 不 仅 仅 是 保 证 各 半 中 的 所 有 线 程 都 读 取 相 同 的 地 址 , 因 为 未 来 速 的 器<br />

5.1.2.4 纹 理 存 储 器<br />

设 备 可 能 要 求 全 速 读 取 。 的<br />

warp 半 于 对<br />

的 所 有 线 程 来 说 , 只 要 所 有 线 程 都 读 取 同 一 个 地 址 , 从 常 量 缓 存 读 取 的 速 度 就 与 读 取 寄 存<br />

宽 要 求 , 但 不 涉 及 拾 取 延 迟 。 带<br />

(streaming 也 fetch),<br />

5.1.2.5 共 享 存 储 器<br />

理 存 储 器 空 间 会 被 缓 , 因 此 纹 理 拾 取 仅 需 在 缓 存 丢 失 时 读 取 一 次 设 备 存 储 器 , 否 则 只 需 读 取 纹 理 缓 存 纹<br />

从 全 局 存 储 器 或 常 量 存 储 器 读 取 设 备 存 储 器 的 方 法 相 比 , 通 过 纹 理 拾 取 读 取 设 备 存 储 器 可 能 是 一 种 更 有 与<br />

warp 。 纹 理 缓 存 已 为 二 维 空 间 位 置 而 优 化 , 因 此 读 取 相 邻 纹 理 地 址 的 同 一 个 可 即<br />

的 线 程 将 实 现 最 高 性<br />

于 共 享 存 储 位 于 芯 片 上 , 因 而 共 享 存 储 器 空 间 比 本 地 和 全 局 存 储 器 空 间 的 速 度 都 要 快 得 多 。 实 际 上 , 对 中 的 所 有 线 程 来 说 , 只 要 线 程 间 不 存 在 存 储 体 冲 突 问 共 享 存 储 器 的 速 度 就 与 访 问 寄 存 器 一 样 快 , 下 面 将 详 细 介 绍 相 关 内 容 。 由<br />

于 warp<br />

能 。 此 外 , 它 设 计 用 于 以 固 定 的 延 迟 执 行 流 式 拾 取<br />

DRAM 说 , 一 次 缓 存 命 中 将 减 少 是 就<br />

44 <strong>CUDA</strong><br />

但 若 一 个 储 器 请 求 的 两 个 地 址 落 入 同 一 个 存 储 体 内 , 就 会 出 现 存 储 体 冲 突 , 访 问 必 须 串 行 化 。 硬 件 会 在 必 要 时 将 存 在 存 储 体 冲 突 的 存 储 器 请 求 分 割 为 多 个 不 冲 突 的 请 求 , 此 时 有 效 带 宽 将 降 低 为 原 带 宽 除 以 分 离<br />

编<br />

5.4 的 替 代 方 法 , 详 见 第 势 优<br />

。<br />

实 现 , 得 到 更 高 效 的 带 宽 , 可 达 到 单 独 一 个 模 块 的 带 宽 的 n<br />

。<br />

这<br />

2.0 南 , 版 本 指 程<br />

为 了 获 得 较 高 的 存 储 器 带 宽 , 共 享 存 储 器 被 划 分 为 多 个 大 小 相 等 的 存 储 器 模 块 , 称 为 存 储 体<br />

n 储 体 可 同 时 访 问 。 因 此 , 对 落 入 存 些<br />

n 存 储 体 的 同 不<br />

地 址 的 任 何 存 储 器 读 取 或 写 入 请 求 都 可 同 时<br />

n 存 储 器 请 求 的 数 量 。 如 果 分 离 后 的 存 储 器 请 求 数 量 为 n, 就 可 以 说 初 始 存 储 器 请 求 导 致 了 的 后


块<br />

和<br />

展<br />

个 的 位<br />

,warp<br />

块 块 块<br />

位<br />

位<br />

是<br />

展<br />

块<br />

等<br />

时<br />

节<br />

是<br />

(stride)<br />

位<br />

块<br />

和<br />

是 时<br />

__shared__ float shared[32];<br />

float data = shared[BaseIndex + s * tid];<br />

存<br />

的 和 访 的 是<br />

位<br />

tid 进<br />

的<br />

块<br />

的<br />

突 。<br />

存 储 体 冲 突 。 为 了 获 得 最 大 化 的 性 能 , 有 必 要 理 解 存 储 器 地 址 如 何 映 射 到 存 储 体 以 调 度 存 储 器 请 求 , 以 最 小 化 存 储 体 冲<br />

(n-way)<br />

32 共 享 存 储 器 空 间 , 存 储 体 采 用 了 这 样 一 种 组 织 方 式 : 为 连 续 的 存 储 体 分 配 连 续 的 于 对<br />

字 , 每 个 存 储<br />

32 带 宽 都 是 的 体<br />

/2<br />

钟 周 期 。 时<br />

1.x 计 算 能 力 为 于 对<br />

设 备<br />

大 小 是 32, 的<br />

体 的 数 量 为 16( 储<br />

5.1 第 见<br />

);warp<br />

的 共<br />

参<br />

为<br />

warp 储 器 请 求 将 分 割 为 一 个 针 对 存 享<br />

warp 部 分 的 请 求 和 一 个 针 对 半 上<br />

下 半 部 分 的 请 求 。 因 而 , 属<br />

于 warp<br />

warp 部 分 的 线 程 和 属 于 一 第<br />

二 部 分 的 线 程 之 间 不 可 能 出 现 存 储 体 冲 突 。 第<br />

32 常 见 的 情 况 就 是 各 线 程 访 问 数 组 中 的 种 一<br />

ID 使 用 线 程 , 字<br />

行 索 引 , 步 幅<br />

s:<br />

是<br />

的<br />

s*n 例 中 , 只 要 本 在<br />

m 体 储 存<br />

n , 或 者 说 只 要 数 倍<br />

m/d<br />

d ( 其 中 数 倍<br />

m<br />

s<br />

最 大 公<br />

char 数<br />

__shared__ char shared[32];<br />

char data = shared[BaseIndex + tid];<br />

, 则 将 出 现 存 储 体 冲 突 : 组<br />

和<br />

位<br />

属<br />

tid ), 线 程 数 约<br />

tid+n<br />

warp 就 是 同 一 个 存 储 体 。 因 而 , 只 有 在 的 问<br />

m/d 半 大 小 小 于 等 于 一 的<br />

,<br />

1.x 会 存 在 存 储 体 冲 突 。 对 于 计 算 能 力 是 不 才<br />

d , 可 以 说 只 有 在 备 设<br />

于 1<br />

s 者 说 只 有 在 或 ,<br />

图 5-5<br />

图 5-6<br />

5-7 无 冲 突 存 储 器 访 问 的 示 例 , 图 了 示<br />

了 导 致 存 储 体 冲 突 的 存 储 器 访 问 示 例 。 示<br />

char data = shared[BaseIndex + 4 * tid];<br />

double<br />

__shared__ double shared[32];<br />

double data = shared[BaseIndex + tid];<br />

位 数<br />

突 , 但 若 通 过 以 下 方 式 访 问 同 一 个 数 组 : 路 冲<br />

操<br />

m 时 , 才 不 会 存 在 存 储 体 冲 突 , 因 为 数 奇<br />

2<br />

。 幂<br />

shared[0]、shared[1]、shared[2] 来 说 , 由 于 例 举<br />

shared[3]<br />

于 同 一 个 存 储 体 。 因 此 不 存 在 存 储 体<br />

32 值 得 注 意 的 情 况 还 包 括 在 各 线 程 访 问 小 于 或 大 于 他 其<br />

元 素 时 。 举 例 来 说 , 如 果 通 过 以 下 方 式 访 问 的<br />

__shared__ int shared_lo[32];<br />

__shared__ int shared_hi[32];<br />

double dataIn;<br />

shared_lo[BaseIndex + tid] = __double2loint(dataIn);<br />

shared_hi[BaseIndex + tid] = __double2hiint(dataIn);<br />

double dataOut =<br />

__hiloint2double(shared_hi[BaseIndex + tid],<br />

shared_lo[BaseIndex + tid]);<br />

数 分 割 为 两 部 分 , 如 以 下 示 例 代 码 所 示 : 作<br />

2 存 在 将 组<br />

储 体 冲 突 : 存<br />

__shared__ struct type shared[32];<br />

struct type data = shared[BaseIndex + tid];<br />

这 种 做 法 并 非 总 是 能 够 提 高 性 能 , 在 未 来 的 架 构 中 可 能 表 现 更 差 。 结 构 体 赋 值 将 在 必 要 时 编 译 为 针 对 结 构 体 中 各 成 员 的 多 个 存 储 器 请 求 , 因 此 , 以 下 代 码 : 但<br />

32 存 储 器 请 求 将 编 译 为 两 个 独 立 的 于 由<br />

double 。 在 本 例 中 避 免 存 储 体 冲 突 的 方 法 之 一 就 是 将 求 请<br />

如<br />

定<br />

struct type {<br />

:<br />

};<br />

float x, y, z;<br />

如<br />

得 到 以 下 结 果 将<br />

定<br />

struct type {<br />

float x, y;<br />

};<br />

如<br />

定<br />

struct type {<br />

<strong>CUDA</strong> 编<br />

45<br />

果 type<br />

如 下 , 则 进 行 两 次 有 存 储 体 冲 突 的 存 储 器 读 取 : 义<br />

果 type<br />

如 下 , 则 进 行 三 次 无 存 储 体 冲 突 的 存 储 器 读 取 : 义<br />

32 因 为 每 个 成 员 都 是 使 用 三 个 是 这<br />

作 为 步 幅 访 问 的 。 字<br />

32 因 为 每 个 成 员 都 是 使 用 两 个 是 这<br />

作 为 步 幅 访 问 的 。 字<br />

2.0 南 , 版 本 指 程<br />

果 type<br />

如 下 , 则 进 行 两 次 有 存 储 体 冲 突 的 存 储 器 读 取 : 义


展<br />

位<br />

(step),<br />

个<br />

块<br />

(random<br />

无<br />

permutation)。<br />

块<br />

(subset)<br />

位<br />

位<br />

位<br />

字 内 的 地 址 时 , 这 会<br />

};<br />

float f;<br />

char c;<br />

字 的 存 储 器 读 取 请 求 提 供<br />

5 因 为 每 个 成 员 都 是 使 用 是 这<br />

选<br />

终 , 共 享 存 储 器 也 会 运 用 一 种 广 播 服 务 时 同 步 将 其 读 取 并 广 播 给 多 个 线 程 。 在 最<br />

半 warp<br />

32 从 而 能 够 在 对 一 个 , 制<br />

子<br />

节 作 为 步 幅 访 问 的 。 机 减 少 存 储 体 冲 突 的 数 量 。 更 精 确 地 来 说 , 包 含 多 个 地 址 的 存 储 器 读 取 请 求 是 通 过 几 个 步 骤 逐 渐 完 成 的 —— 字<br />

提<br />

(broadcas)<br />

广<br />

每<br />

32 个 线 程 读 取 同 一 个 多 的<br />

剩<br />

两 个 时 钟 周 期 一 步 为 一 个 无 存 储 体 冲 突 子 集 提 供 服 务 ; 在 每 个 步 骤 中 都 通 过 以 下 步 骤 在 尚 未 被 服 务 的 地 址 中 建 立 子 集 : 每<br />

供 服 务 , 直 至 为 所 有 地 址<br />

剩 一 个 字 作 为 广 播 字 ; 集 中 包 括 : 播 字 内 的 所 有 地 址 ; 择<br />

地 址 指 向 的 各 存 储 体 的 地 址 。 不 指 定 在 每 个 周 期 选 择 哪 个 字 作 为 广 播 字 以 及 为 各 存 储 体 选 择 哪 个 地 址 。 余<br />

图 5-8<br />

了 包 括 广 播 机 制 在 内 的 存 储 器 读 取 访 问 的 示 例 。 示<br />

warp 常 见 的 无 冲 突 情 况 就 是 半 种 一<br />

32 所 有 线 程 都 读 取 同 一 个 的 中<br />

内 的 地 址 。 字<br />

右 侧 : 随 机 排 列<br />

无 存 储 体 冲 突 的 共 享 存 储 器 访 问 模 式 示 例<br />

的 线 性 寻 址 。 字<br />

46 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程<br />

32 : 步 幅 为 一 个 侧 左<br />

图 5-5.


位<br />

的 线 性 寻 址 。 字<br />

程 指 南 , 版<br />

无 存 储 体 冲 突 的 共 享 存 储 器 访 问 模 式 示 例<br />

<strong>CUDA</strong> 编<br />

47<br />

32 为 三 个 幅 步<br />

图 5-6.<br />

本 2.0


个 位<br />

位<br />

有<br />

例<br />

二 字 的 线 性 寻 址 将 导 致 八 路 存 储 体 冲 突 。<br />

例 有 存 储 体 冲 突 的 共 享 存 储 器 访 问 模 式 示 2 : 步 幅 为 侧 左<br />

图 5-7.<br />

32<br />

48 <strong>CUDA</strong> 编<br />

8 : 步 幅 为 侧 右<br />

32<br />

2.0 南 , 版 本 指 程


的<br />

。<br />

个<br />

使 用 广 播 机 制 的 共 享 存 储 器 读 取 访 问 模 式 示 例<br />

或<br />

类<br />

内<br />

内 的 地 址 。 的 字 在 第 一 个 步 中 被 选 作 广 播 字 ), 要 么 位<br />

5.1.2.6 寄 存 器<br />

存 储 体 冲 突 路 二 致 导 会<br />

寄 存 器<br />

<strong>CUDA</strong> 编<br />

49<br />

32 : 这 种 访 问 模 式 不 存 在 冲 突 , 因 为 所 有 线 程 都 读 取 同 一 个 侧 左<br />

5 : 这 种 访 问 模 式 要 么 不 会 导 致 存 储 体 冲 突 ( 如 果 存 储 体 侧 右<br />

图 5-8.<br />

般 而 言 , 访 问 寄 存 器 不 会 给 每 条 指 令 带 来 额 外 的 时 钟 周 期 , 但 写 入 后 读 取 依 赖 关 系 和 寄 存 器 的 存 储 体 冲 突 可 能 会 导 致 延 迟 。 一<br />

译 器 和 线 程 调 度 程 序 将 尽 可 能 以 最 优 方 式 调 度 指 令 , 避 免 出 现 寄 存 器 的 存 储 体 冲 突 。 当 每 个 块 的 线 程 数 编<br />

float4 来 说 , 无 需 将 数 据 转 换 成 体 具<br />

int4<br />

。 型<br />

2.0 南 , 版 本 指 程<br />

192 每 个 多 处 理 器 至 少 有 果 如<br />

动 线 程 , 写 入 后 读 取 依 赖 关 系 带 来 的 延 迟 可 忽 略 不 计 。 活<br />

64 是 量<br />

倍 数 时 , 这 种 方 法 的 效 果 最 优 。 除 了 遵 从 此 规 则 之 外 , 应 用 程 序 无 法 直 接 控 制 这 些 存 储 体 冲 突 。


,ceil(T,<br />

节<br />

的<br />

个<br />

的<br />

选<br />

块<br />

或<br />

块<br />

块<br />

或<br />

,B<br />

或<br />

所<br />

个<br />

节<br />

块<br />

或<br />

。<strong>CUDA</strong><br />

,T<br />

或<br />

个<br />

5.2 每 个 块 的 线 程 数 量<br />

定 每 个 网 格 的 线 程 总 数 、 每 线 程 总 数 ( 网 格 包 含 的 块 数 ), 应 选 择 最 大 化 可 用 计 算 资 源 的 利 用 率 。 这 意 味 着 块 的 数 量 至 少 应 与 设 备 中 的 多 处 理 器 数 量 相 同 。 此 外 , 每 个 多 处 理 器 仅 运 行 一 个 块 将 使 多 处 理 器 在 线 程 同 步 过 程 中 出 现 空 闲 , 如 果 每 个 块 中 没 有 足 够 的 线 给<br />

程 可 容 纳 负 载 延 迟 , 则 在 设 备 存 储 器 读 取 过 程 中 也 会 出 现 空 闲 。 因 而 , 最 好 允 许 在 每 个 多 处 理 器 上 存 在 两<br />

或 多 个 活 动 块 , 从 而 允 许 等 待 块 与 运 行 的 块 间 存 在 重 叠 。 为 此 , 块 的 数 量 至 少 应 为 设 备 中 多 处 理 器 数 量 的 二 倍 , 而 且 为 每 个 块 所 分 配 的 共 享 存 储 器 也 至 少 应 为 每 个 多 处 理 器 可 用 的 共 享 存 储 器 总 量 的 一 半 ( 请 参 见 )。 如 果 有 更 多 的 线 程 块 以 流 水 线 的 形 式 通 过 设 备 , 则 开 销 将 进 一 步 降 低 。 个<br />

代 的 设 备 上 。 的 节 数<br />

每 个 块 分 配 更 多 线 程 可 实 现 有 效 的 时 间 分 割 , 但 每 个 块 的 线 程 越 多 , 每 个 线 程 可 用 的 寄 存 器 就 越 少 。 如 为<br />

第 3.1<br />

线 程 数<br />

附<br />

出 的 各 多 处 理 器 的 寄 存 器 总 数 每 个 多 处 理 器 的 活 动 块 数 量 倍 数 。 给<br />

每 个 块 的<br />

32) 是 中 是<br />

四<br />

的<br />

是<br />

是<br />

100;1000 希 望 网 格 有 能 力 扩 展 到 未 来 的 设 备 , 每 个 网 格 的 块 数 量 至 少 应 为 果 如<br />

块 将 能 够 扩 展 到 此 后<br />

内 核 编 译 时 使 用 了 超 过 执 行 配 置 允 许 数 量 的 寄 存 器 , 这 可 能 会 妨 碍 内 核 调 用 。 果<br />

warp 的 数 量 足 够 多 后 , 每 个 块 的 线 程 数 量 应 为 块 在<br />

warp 的 倍 数 , 避 免 因 小 大<br />

填 充 不 足 而 造 成 的 计<br />

64 源 浪 费 , 最 好 使 线 程 数 量 是 资 算<br />

5.1.2.6 , 详 见 第 数 倍<br />

述 。 所<br />

1.x 计 算 能 力 为 于 对<br />

备 来 说 , 每 个 线 程 可 用 的 寄 存 器 数 量 等 于 : 设<br />

long<br />

long, 计 变<br />

R 中 其<br />

录 A<br />

将 T<br />

32 入 为 最 接 近 的 五 舍<br />

–ptxas-options=-v 在 编 译 时 使 用 果 如<br />

, 编 译 器 将 报 告 内 核 编 译 所 使 用 的 寄 存 器 数 量 ( 以 及 本 地 、 共 享 更 高 的 设 备 的 每 个 多 处 理 器 的 寄 存 器 数 量 都 是 项<br />

double 量 存 储 器 使 用 情 况 )。 请 注 意 , 每 个 常 和<br />

long<br />

量 都 为 本 地 支 持 这 些 类 型 的 设 备 使 用 两 个<br />

最 大 化 占 用 率 , 编 译 器 会 尝 试 最 小 化 寄 存 器 的 使 用 , 程 序 员 需 要 谨 慎 选 择 执 行 配 置 供 了 一 份 电 子 表 格 , 可 帮 助 程 序 员 根 据 共 享 存 储 器 和 寄 存 器 要 求 选 择 线 程 块 的 大 小 。 为<br />

1.2 器 , 也 就 是 计 算 能 力 为 存 寄<br />

更 高 的 设 备 对 应<br />

高 的 设 备 对 应 于 更<br />

Development Kit 提<br />

Software<br />

线<br />

于 long<br />

1.3 力 为 能 算<br />

但 计 算 能 力 低<br />

double。<br />

1.2 算 能 力 较 低 的 设 备 相 比 , 计 算 能 力 为 计 与<br />

于 1.2<br />

5.3 宿 主 和 设 备 间 的 数 据 传 输<br />

备 的 二 倍 。 程 是 更 理 想 的 情 况 , 允 许 使 用 足 够 的 寄 存 器 进 行 编 译 。 设<br />

64 块 最 少 有 个 每<br />

192 , 这 仅 在 每 个 多 处 理 器 有 多 个 活 动 块 时 才 是 有 意 义 的 。 每 个 块 程 线<br />

256<br />

warp 多 处 理 器 活 动 个 每<br />

warp 与 活 动 量 数<br />

A 数 量 ( 如 附 录 大 最<br />

示 ) 的 比 率 称 为 多 处 理 器 占 用 率 。<br />

和 设 备 存 储 器 之 间 的 带 宽 比 设 备 存 储 器 和 宿 主 存 储 器 之 间 的 带 宽 高 得 多 。 因 而 , 应 尽 力 最 小 化 宿 主 和 设 备 之 间 的 数 据 传 输 , 例 如 , 将 更 多 代 码 从 宿 主 迁 移 到 设 备 —— 即 便 这 意 味 着 以 并 行 性 更 低 的 计 算 方 式 运 行 内 核 。 设 备 存 储 器 中 可 能 会 创 建 中 间 数 据 结 构 , 由 设 备 , 而 且 在 销 毁 时 不 会 被 宿 主 映 射 , 也 不 会 复 制 到 宿 主 存 储 器 。<br />

外 , 考 虑 到 与 每 相 关 的 开 销 , 将 多 个 较 小 的 传 输 操 作 整 合 为 一 次 较 大 的 成 批 传 输 操 作 的 性 能 总 是 优 于 分 别 进 行 每 一 次 传 输 。 此<br />

50 <strong>CUDA</strong> 编<br />

4.5.1.2 , 在 使 用 分 页 锁 定 存 储 器 时 , 宿 主 和 设 备 间 的 带 宽 更 高 , 如 第 后 最<br />

述 。 所<br />

2.0 南 , 版 本 指 程


节<br />

位<br />

数<br />

之<br />

节<br />

节<br />

或<br />

(locality),<br />

数<br />

位<br />

节<br />

节<br />

5.4 纹 理 拾 取 与 全 局 或 常 量 存 储 器 读 取 的 对 比<br />

<br />

<br />

它<br />

节<br />

节<br />

寻<br />

打<br />

<br />

8<br />

4.3.4.1 节 位<br />

1.0]<br />

;<br />

1.0] 区<br />

是 缓 存 的 , 因 而 假 如 纹 理 拾 取 中 存 在 数 据 局 部 性 理 拾 取 将 表 现 出 更 高 的 带 宽 ; 它 们 不 受 制 于 存 储 器 访 问 模 式 的 限 制 , 而 全 局 或 常 量 存 储 器 读 取 必 须 遵 从 此 类 限 制 以 获 得 较 好 的 性 能<br />

读 取 全 局 或 常 量 存 储 器 相 比 , 通 过 纹 理 拾 取 实 现 设 备 存 储 器 读 取 有 着 一 些 优 势 : 纹 与<br />

计 算 的 延 迟 得 到 了 更 好 的 隐 藏 , 可 能 改 进 执 行 随 机 数 据 访 问 的 应 用 程 序 的 性 能 ; 址<br />

包 的 数 据 可 通 过 一 次 操 作 广 播 给 不 同 的 变 量<br />

5.1.2.1 参 见 第 请 (<br />

和 5.1.2.3<br />

);<br />

)。<br />

和 16<br />

[0.0, 输 入 数 据 可 转 换 为 型 整<br />

[-1.0,<br />

32 的 内 间<br />

点 值 ( 请 参 见 第 浮<br />

, 特 别 是 图 像 处 理 :<br />

特 性<br />

适 用 场 景 用<br />

提 示<br />

5.5 整 体 性 能 优 化 策 略<br />

一 的 纹 理 坐 标 独 立 于 分 辨 率 的 编 码 寻 址 模 式 自 动 处 边 界 情 况 仅 适 用 于 归 一 化 坐 标 但 在 个 内 核 调 用 中 , 纹 理 缓 存 不 会 在 全 局 存 储 器 写 入 方 面 保 持 连 贯 性 , 因 此 如 果 纹 理 拾 取 针 对 的 是 通 归<br />

<strong>CUDA</strong><br />

化<br />

一 内 核 调 用 的 全 局 写 入 操 作 写 入 的 地 址 , 则 将 返 回 不 确 定 的 数 据 。 换 句 话 说 仅 在 存 储 器 位 置 已 由 之 前 内 核 调 用 存 储 器 复 制 更 新 时 , 线 程 才 能 通 过 纹 理 安 全 读 取 某 些 存 储 器 位 置 , 但 如 果 已 由 同 一 内 核 调 用 的 同 一 线 程 或 其 他 线 程 更 新 , 则 并 非 如 此 。 二 者 仅 在 使 用 无 法 写 入 组 的 内 核 从 线 性 存 储 器 拾 取 时 才 有 所 相 关 。 同 过<br />

<strong>CUDA</strong> 纹 理 是 一 个 果 如<br />

4.3.4.2 请 参 见 第 ( 组<br />

), 硬 件 提 供 的 其 他 功 能 可 能 对 不 同 的 应 用 程 序 非 常 有<br />

Texel 滤 过<br />

的 快 速 、 低 精 度 的 插 值 仅 在 纹 理 参 考 返 回 浮 点 数 据 时 有 效 间<br />

最<br />

能 优 化 是 以 三 项 基 本 策 略 为 基 础 演 化 出 来 的 : 大 化 并 行 执 行 ; 性<br />

优<br />

优<br />

__syncthreads(), 在<br />

需 要 同 步 以 彼 此 共 享 数 据 而 被 打 破 时 可 能 出 现 两 种 情 况 : 这 些 线 程 可 能 属 于 同 一 个 块 , 此 时 应 使 用 同 一 个 内 核 调 用 中 同 步 共 享 存 储 器 共 享 数 据 ; 如 果 属 于 不 同 的 块 , 此 时 必 须 使 用 两 个 独 立 的 内 核 调 用 通 过 全 局 存 储 器 共 享 数 据 , 一 个 用 于 写 入 全 局 存 储 器 , 一 个 用 于 读 取 全 局 存 储 器 。 程<br />

存 储 器 利 用 率 , 实 现 最 大 的 存 储 器 带 宽 ; 化 指 令 利 用 率 , 实 现 最 大 化 的 指 令 吞 吐 量 。 最 大 化 并 行 执 行 的 第 一 步 就 是 结 构 化 算 法 , 尽 可 能 地 寻 找 到 更 多 的 数 据 并 行 性 。 当 算 法 的 并 行 性 因 某 些 线<br />

一 旦 算 法 的 并 行 性 被 找 到 , 就 需 要 尽 可 能 有 效 地 在 硬 件 实 现 。 这 是 通 过 谨 慎 选 择 各 内 核 调 用 的 执 行 配 置 完<br />

节 现 数 量 级 的 变 化 。 优 化 存 储 器 利 用 率 的 下 一 步 骤 是 根 据 最 优 的 存 储 器 访 问 模 式 , 尽 可 能 以 最 优 方 式 组 织 存 和<br />

用 程 序 还 应 最 大 化 宿 主 和 设 备 间 的 并 发 执 行 。 优 化 存 储 器 利 用 率 的 第 一 步 是 最 小 化 低 带 宽 的 数 据 传 输 。 这 也 就 意 味 着 最 小 化 宿 主 和 设 备 之 间 的 数 据 传 应<br />

<strong>CUDA</strong> 编<br />

51<br />

4.5.1.5 程 序 还 应 在 较 高 的 层 面 最 大 化 并 行 执 行 , 通 过 流 在 设 备 上 显 式 寻 找 并 发 执 行 , 如 第 用 应<br />

所 述 ,<br />

5.2 , 详 细 内 容 请 参 见 第 的 成<br />

。<br />

佳 优 化 方 法 可 能 是 首 先 避 免 进 行 任 何 数 据 传 输 , 直 接 在 需 要 的 位 置 重 新 计 算 数 据 。 最<br />

5.1.2.1、5.1.2.3、5.1.2.4 第 如<br />

5.1.2.5<br />

所 述 , 根 据 各 类 存 储 器 的 访 问 模 式 的 不 同 , 有 效 带 宽 可 能 会 出<br />

2.0 南 , 版 本 指 程<br />

5.3 如 第 , 输<br />

所 述 , 因 为 此 类 传 输 比 设 备 和 全 局 存 储 器 之 间 的 数 据 传 输 带 宽 低 得 多 。 这 也 意 味 着 通 过 最<br />

5.1.2 设 备 共 享 存 储 器 的 使 用 来 尽 可 能 地 减 少 设 备 和 全 局 存 储 器 之 间 的 数 据 传 输 , 如 第 化 大<br />

所 述 。 有 时 ,


节<br />

特<br />

(B.2 节 节 器 访 问 。 这 种 优 化 对 于 全 局 存 储 器 访 问 尤 为 重 要 , 因 为 全 局 存 储 器 的 带 宽 较 低 , 其 延 迟 可 能 达 到 百 个 进 行 共 享 存 储 器 访 问 优 化 。 储<br />

, 在 不 影 响 最 终 结 果 的 前 提 下 提 高 速 度 , 例 如 使 用 内 建 函 数 而 非 一 般 函 数 列 举 了 内 建 函 数 )、 度<br />

5.1.1.3 周 期 ( 请 参 见 第 钟 时<br />

)。 另 一 方 面 , 通 常 只 有 在 共 享 存 储 器 访 问 中 存 在 严 重 的 存 储 体 冲 突 时 才<br />

5.1.1.1 指 令 利 用 率 的 优 化 , 应 最 小 化 低 吞 吐 量 的 数 学 指 令 的 使 用 ( 请 参 见 第 于 对<br />

)。 这 包 括 权 衡 计 算 精<br />

SIMT 单 精 度 而 非 双 精 度 。 由 于 设 备 的 用 使<br />

5.1.1.2 应 特 别 注 意 控 制 流 指 令 , 如 第 , 性<br />

述 。 所<br />

52 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


相<br />

所<br />

选<br />

,Csub 等<br />

更 高 的 通 用 矩 阵 乘 法 实 现 。 能<br />

的<br />

和<br />

的<br />

的<br />

程 指 南 , 版<br />

和<br />

的 的 的<br />

编<br />

矩<br />

的<br />

块<br />

的<br />

的<br />

节<br />

同 时 保 的 子 阵 , 它 的 行 索 引 ),<br />

第 6 章 矩 阵 乘 法 示 例<br />

6.1 概 述<br />

hA)<br />

wA) 的<br />

<br />

块<br />

程<br />

Csub<br />

线<br />

的<br />

为 (wA,<br />

(wB,<br />

wA)<br />

一 个 子 方 矩<br />

录 A)。 使<br />

block_size)<br />

积 C, 此 任 务 将 以 如 下 方 法 划 分 为 几 个 乘<br />

小 的 倍 数 ( 请 参 见 具 大<br />

阵 A<br />

B 阵 矩<br />

C 线 程 块 均 负 责 计 算 个 每<br />

计 算 维 度 分 别<br />

阵 Csub;<br />

:<br />

证 不 超 过 每 个 块 的 最 大 线 程 数 ( 附 示 维<br />

Csub 每 个 线 程 负 责 计 算 的 内<br />

一 个 元 素<br />

度 block_size<br />

。<br />

为 16,<br />

warp 块 的 线 程 数 是 个 每<br />

第 5.2<br />

如<br />

和<br />

的<br />

/ block_size)。<br />

为 block_size<br />

图 6-1<br />

通 过 这 种 方 法 安 排 计 算 , 我 们 就 利 用 了 速 度 较 快 的 共 享 存 储 器 , 节 省 了 大 量 全 局 存 储 器 带 宽 , 这 是 因 为 从<br />

(wA, 下 两 个 长 方 矩 阵 的 乘 积 : 维 度 为 以 于<br />

A<br />

方 阵 , 通 过 计 算 这 些 方 阵 的 乘 积 和 来 计<br />

源 , 这 两 个 长 方 矩 阵 被 分 割 为 多 维 度 每 个 乘 积 首 先 都 从 全 局 存 储 器 将 两 个 对 应 的 方 阵 载 入 共 享 存 储 器 , 使 用 一 个 线 程 载 入 各 矩 阵 的 一 个 元 素 , 然 后 由 各 线 程 来 计 算 乘 积 的 一 个 元 素 。 各 线 程 将 所 有 这 些 乘 积 的 结 果 汇 总 到 一 个 寄 存 器 中 , 完 成 后 , 将 结 果 写 入 全 局 存 储 器 。 资<br />

算 Csub。<br />

与 Csub<br />

(block_size, 维 度 为 ; 同<br />

B<br />

Csub , 它 与 阵 子<br />

有 相 同 的 列 索 引 。 为 了 适 应 设 备 的<br />

A 存 储 器 中 读 取 局 全<br />

B<br />

(wA 仅 为 数 次<br />

<strong>CUDA</strong> 编 写 本 示 例 时 , 我 们 仅 以 展 示 各 种 在 而<br />

程 原 则 为 目 标 , 所 以 在 实 际 应 用 中 , 请 探 索 比 本 示 例 性<br />

每 个 线 程 块 计<br />

一 个 子 矩<br />

内 的 每 个 线 程 计<br />

个 元 素 。 一<br />

<strong>CUDA</strong> 编<br />

53<br />

矩 阵 乘 法 块<br />

本 2.0<br />

算 C<br />

阵 Csub。<br />

算 Csub<br />

图 6-1.


6.2 源 代 码 清 单<br />

// Thread block size<br />

#define BLOCK_SIZE 16<br />

// Forward declaration of the device multiplication function<br />

__global__ void Muld(float*, float*, int, int, float*);<br />

// Host multiplication function<br />

// Compute C = A * B<br />

// hA is the height of A<br />

// wA is the width of A<br />

// wB is the width of B<br />

void Mul(const float* A, const float* B, int hA, int wA, int wB,<br />

float* C)<br />

{<br />

int size;<br />

// Load A and B to the device<br />

float* Ad;<br />

size = hA * wA * sizeof(float);<br />

cudaMalloc((void**)&Ad, size);<br />

cudaMemcpy(Ad, A, size, cudaMemcpyHostToDevice);<br />

float* Bd;<br />

size = wA * wB * sizeof(float);<br />

cudaMalloc((void**)&Bd, size);<br />

cudaMemcpy(Bd, B, size, cudaMemcpyHostToDevice);<br />

// Allocate C on the device<br />

float* Cd;<br />

size = hA * wB * sizeof(float);<br />

cudaMalloc((void**)&Cd, size);<br />

// Compute the execution configuration assuming<br />

// the matrix dimensions are multiples of BLOCK_SIZE<br />

dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);<br />

dim3 dimGrid(wB / dimBlock.x, hA / dimBlock.y);<br />

// Launch the device computation<br />

Muld(Ad, Bd, wA, wB, Cd);<br />

// Read C from the device<br />

cudaMemcpy(C, Cd, size, cudaMemcpyDeviceToHost);<br />

// Free device memory<br />

cudaFree(Ad);<br />

cudaFree(Bd);<br />

cudaFree(Cd);<br />

}<br />

// Device multiplication function called by Mul()<br />

// Compute C = A * B<br />

// wA is the width of A<br />

// wB is the width of B<br />

__global__ void Muld(float* A, float* B, int wA, int wB, float* C)<br />

{<br />

// Block index<br />

int bx = blockIdx.x;<br />

int by = blockIdx.y;<br />

// Thread index<br />

int tx = threadIdx.x;<br />

int ty = threadIdx.y;<br />

// Index of the first sub-matrix of A processed by the block<br />

int aBegin = wA * BLOCK_SIZE * by;<br />

// Index of the last sub-matrix of A processed by the block<br />

int aEnd = aBegin + wA - 1;<br />

// Step size used to iterate through the sub-matrices of A<br />

int aStep = BLOCK_SIZE;<br />

// Index of the first sub-matrix of B processed by the block<br />

int bBegin = BLOCK_SIZE * bx;<br />

// Step size used to iterate through the sub-matrices of B<br />

int bStep = BLOCK_SIZE * wB;<br />

// The element of the block sub-matrix that is computed<br />

// by the thread<br />

float Csub = 0;<br />

// Loop over all the sub-matrices of A and B required to<br />

// compute the block sub-matrix<br />

54 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


,Muld() 将<br />

的<br />

将 相<br />

的<br />

程 指 南 , 版<br />

的<br />

和<br />

中<br />

分<br />

所<br />

(wrapper);<br />

C; ; ; 和<br />

。<br />

}<br />

for (int a = aBegin, b = bBegin;<br />

a


,Csub 计<br />

是<br />

和<br />

都<br />

的<br />

,Muld() 会<br />

节<br />

,ty<br />

节<br />

节<br />

。<br />

,tx 在<br />

至<br />

<br />

再 计<br />

Muld() 的<br />

b<br />

和<br />

这 里 也 不 存 在 任 何 存 储 体 冲 突 , 因 为 在 每 个<br />

中<br />

15 之<br />

实 际 上 , 假<br />

存 等<br />

。<br />

块 对 于 所 有 线 程 都 是 相 同 的 和 存 储 器 访 问 时 都 会 访 问 不 同 储 器 访 问 时 访 问 相 同 的 存 储 体 。 的<br />

为 a、<br />

两 个 子 阵 的 乘 积 , 并 将 其 与 上 一 次 循 环 获 得 的 乘 积 相 加 ; 次 进 行 同 步 , 以 确 保 两 个 子 阵 的 乘 积 运 算 已 完 成 , 之 后 才 开 始 下 一 次 循 环 处 理 所 有 子 阵 之 后 算 完 成 将 结 果 写 入 全 局 存 储 器 。 算<br />

述 , 此 时 将 能 够 确 保 全 局 存 储 器 合 并 , 因 倍 数 。 所<br />

5.1.2.1 目 的 是 为 了 最 大 化 存 储 器 性 能 , 请 参 见 第 写 编<br />

5.1.2.5 第 和<br />

设 wA<br />

wB<br />

16<br />

5.1.2.1 , 如 第 数 倍<br />

c<br />

是 BLOCK_SIZE(<br />

半 warp<br />

于 16)<br />

0<br />

As[ty][tx]、Bs[ty][tx] 因 此 每 个 线 程 在 进 行 , 间<br />

k<br />

As[ty][k] 储 体 , 而 在 进 行 存 的<br />

Bs[k][tx]<br />

56 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


的<br />

节<br />

节<br />

节<br />

附 录 A 技 术 规 范<br />

A.1 一 般 规 范<br />

GeForce GTX 280 30 1.3<br />

GeForce GTX 260 24 1.3<br />

GeForce 9800 GX2 2×16 1.1<br />

GeForce 9800 GTX 16 1.1<br />

GeForce 8800 Ultra, 8800 GTX 16 1.0<br />

GeForce 8800 GT 14 1.1<br />

GeForce 9600 GSO, 8800 GS, 8800M GTX 12 1.1<br />

GeForce 8800 GTS 12 1.0<br />

GeForce 9600 GT, 8800M GTS 8 1.1<br />

GeForce 9500 GT, 8600 GTS, 8600 GT,<br />

面 的 内 容 描 述 了 与 各 种 计 算 能 力 相 关 联 的 技 术 规 范 和 特 性 。 若 无 其 他 说 明 , 给 定 计 算 能 力 的 规 范 与 略 低 计 算 能 力 的 规 范 相 同 。 类 似 地 , 计 算 能 力 向 下 兼 容 。 下 多 处 理 器 数 量<br />

计 算 能 力<br />

4 1.1<br />

8700M GT, 8600M GT, 8600M GS<br />

GeForce 8500 GT, 8400 GS, 8400M GT,<br />

8400M GS<br />

2 1.1<br />

GeForce 8400M G 1 1.1<br />

Tesla S1070 4×30 1.3<br />

Tesla C1060 30 1.3<br />

Tesla S870 4×16 1.0<br />

1.0<br />

4×16 2×16<br />

Tesla D870<br />

Tesla C870 16 1.0<br />

Quadro Plex 1000 Model S4 1.0<br />

Quadro Plex 1000 Model IV<br />

Quadro FX 5600 1.0<br />

Quadro FX 3700 14 1.1<br />

Quadro FX 3600M 12 1.1<br />

Quadro FX 4600 12 1.0<br />

Quadro FX 1700, FX 570, NVS 320M, FX 1600M,<br />

FX 570M<br />

4 1.1<br />

Quadro FX 370, NVS 290, NVS 140M, NVS 135M,<br />

FX 360M<br />

2 1.1<br />

Quadro NVS 130M 1 1.1<br />

2.5 设 备 的 一 般 规 范 取 决 于 其 计 算 能 力 ( 请 参 见 第 算 计<br />

)。<br />

<strong>CUDA</strong> 列 出 了 所 有 支 持 表 下<br />

备 的 多 处 理 器 数 量 和 计 算 能 力 : 设<br />

1.0<br />

A.1.1<br />

计 算 能 力 1.0 的 规 范<br />

<strong>CUDA</strong><br />

每 个 块 的 最 大 线 程 数 编<br />

和 )。<br />

57<br />

第 4.5.3.2<br />

2.0 南 , 版 本 指 程<br />

4.5.2.2 用 运 行 时 查 询 时 钟 频 率 和 设 备 存 储 器 总 量 ( 请 参 见 第 使 可<br />

为 512;


和<br />

维<br />

遇<br />

位<br />

(rounding<br />

和<br />

在<br />

节<br />

方<br />

;<br />

节<br />

)。<br />

字 上 操 作 的 原 子 函 数 ( 请 参 见 位<br />

舍<br />

的<br />

NaN) 编 码 , 但 实 异<br />

;<br />

Warp<br />

<br />

<br />

<br />

<br />

<br />

常 量 存 储 器 的 总 量 块<br />

<br />

<br />

每 纹<br />

<br />

<br />

对 <br />

32 程 线 个 内<br />

个<br />

程 ;<br />

可 用 的 共 享 存 储 器 数 量 组 线<br />

量 是 每 个 多 处 理 理 存 储 器 的 缓 存 工 作 区 介 于 每 个 多 处 理 到 个 多 处 理 器 的 最 大 活 动 块 数 是 8; 块 常<br />

8192;<br />

16KB,<br />

64KB;<br />

器 8KB;<br />

6 8KB<br />

是<br />

器 是 是<br />

于 绑 定 到 线 性 存 储 器 的 纹 理 参 考 , 最 大 宽 度 数 个 万<br />

指<br />

; 令<br />

16<br />

之 为 织<br />

27;<br />

个<br />

13;<br />

间<br />

11, 最 16,<br />

存 储 体 ( 请 参 见<br />

个<br />

11, 最 15;<br />

第 5.1.2.5<br />

节<br />

);<br />

11;<br />

块<br />

x、y 线 程 块 的 个 一<br />

z<br />

512、512 大 规 格 分 别 为 最 的<br />

64;<br />

程 块 网 格 各 维 度 的 最 大 规 格 为 65535; 线<br />

32 小 是 大 的<br />

个 多 处 理 器 的 寄 存 器 数 量<br />

warp 处 理 器 的 最 大 活 动 多 个<br />

是 24; 数<br />

多 处 理 器 的 最 大 活 动 线 程 数 是 768; 个<br />

<strong>CUDA</strong> 定 到 一 维 绑 于<br />

2 纹 理 参 考 , 最 大 宽 度 为 的 组<br />

<strong>CUDA</strong> 定 到 二 维 绑 于<br />

2 纹 理 参 考 , 最 大 宽 度 为 的 组<br />

2 度 为 高 大<br />

A.1.2<br />

计 算 能 力 1.1 的 规 范<br />

<strong>CUDA</strong> 定 到 三 维 绑 于<br />

2 纹 理 参 考 , 最 大 宽 度 为 的 组<br />

2 度 为 高 大<br />

2 度 为 深 大<br />

支<br />

A.1.3<br />

计 算 能 力 1.2 的 规 范<br />

计 算 能 力<br />

。<br />

为 2<br />

200 小 限 制 为 大 核<br />

PTX<br />

8 多 处 理 器 都 由 个 每<br />

4 器 组 成 , 因 此 一 个 多 处 理 器 能 够 在 理 处<br />

warp 周 期 内 处 理 一 个 钟 时<br />

<br />

<br />

<br />

每 支<br />

vote 函<br />

在 全 局 存 储 器 持<br />

持 在 共 享 存 储 器 中 操 作 的 原 子 函 数 以 及 在 全 局 存 储 器 支<br />

块<br />

的 32<br />

4.4.4 操 作 的 原 子 函 数 ( 请 参 见 第 上 字<br />

);<br />

A.1.4<br />

节<br />

计 算 能 力 1.3 的 规 范<br />

是 1024。<br />

的 64<br />

第 4.4.4<br />

支<br />

A.2 浮 点 标 准<br />

多 处 理 器 的 最 大 活 动 线 程 数 个<br />

双 精 度 浮 点 数 。 持<br />

持 warp<br />

4.4.5 请 参 见 第 ( 数<br />

多 处 理 器 的 寄 存 器 数 量 是 16384; 个<br />

);<br />

warp 处 理 器 的 最 大 活 动 多 个<br />

量 是 32; 数<br />

<br />

标<br />

mode); 但<br />

存 在 动 态 可 配 置 的 舍 入 模 式 函 数 公 开 ; 不<br />

<br />

, 但 有 以 下 例 外 : 入 模 式 , 可 通 过 设 备 准<br />

常 被 掩 藏 一 样 , 并 且 这 种 隐 藏 的<br />

绝<br />

58 <strong>CUDA</strong> 编<br />

存 在 检 测 发 生 浮 点 异 常 的 机 制 , 所 有 操 作 的 行 为 就 到 异 常 事 件 时 一 样 ; 同 样 , 尽 管 支 不<br />

IEEE-754 计 算 设 备 都 符 合 针 对 二 进 制 浮 点 算 术 的 有 所<br />

IEEE-574 和 负 数 不 符 合 值 对<br />

2.0 南 , 版 本 指 程<br />

IEEE 数 操 作 都 支 持 多 大<br />

NaN<br />

面 的 规 定 , 它 们 将 按 原 样 传 递<br />

像 IEEE-754<br />

与 IEEE-754<br />

持 SNaN(Signaling<br />

持 Signaling;<br />

达 方 式 际 上 不 支 表


(round-towards-zero),<br />

:<br />

(denormalized<br />

参<br />

程 指 南 , 版<br />

的<br />

它 (FMAD),<br />

(round-to-nearest-even)<br />

请 NaN),<br />

的<br />

构 的 处 理 方 式 不 同 。 架<br />

对<br />

<br />

精 度 浮 点 数 加 单 于<br />

<br />

<br />

<br />

<br />

平 除<br />

加<br />

number); 浮<br />

<br />

<br />

下<br />

- 乘 法 往 往 结 合 为 一 条 乘 和 法<br />

令 法 是 通 过 倒 数 、 以 非 标 准 的 方 式 实 现 的 ; 指<br />

截 取 乘 法 的 中 间 结 果 ; 将<br />

根 是 以 非 标 准 的 方 式 通 过 倒 数 平 方 根 实 现 的 ; 不 方<br />

和<br />

的 结 果 将 被 刷 新 为 零 ; 涉 及 一 个 或 多 个 输 操 作 的 结 果 是 位 模 意 : 溢<br />

加 以 注<br />

于 加 法 和 乘 法 , 仅 支 持 通 过 静 态 舍 入 模 式 实 现 舍 入 到 最 近 的 偶 数 零 舍 入 支 持 向 正 负 无 穷 大 方 向 的 舍 入 ; 对<br />

向<br />

仅<br />

<br />

标<br />

舍<br />

模 式 是 舍 入 到 最 近 的 偶 数 或 的 入<br />

其 但<br />

不 支 持 反 向 规 格 化 数<br />

点 算 术 和 比 较 指 令 会 在 浮 点 操 作 之 前 将 操 作 数 反<br />

规 格 化 为 零 ; 向<br />

于 双 精 度 浮 点 数 : 对<br />

IEEE-754<br />

而 言 , 采 用 将 数 限 定 在 所 支 持 的 范 围 尾 端 的 方 法 。 这 并<br />

入 NaN<br />

式 0x7fffffff<br />

QNaN(Quiet<br />

未 定 义 在 浮 点 值 超 出 整 型 格 式 的 范 围 的 情 况 下 , 浮 点 值 到 整 型 值 的 转 换 方 式 。 对 于 计 算 设 备<br />

NaN 数 不 是 , 则 结 果 为 非 参 他<br />

。 数<br />

IEEE 、 除 法 和 平 方 根 运 算 中 惟 一 支 持 的 数 倒<br />

IEEE-754R 据 根<br />

fminf()、fmin()、fmaxf() 如 果 , 准<br />

fmax()<br />

与 x86<br />

是 的 输 入 参 数 之 一 是 NaN,<br />

<strong>CUDA</strong> 编<br />

59<br />

本 2.0


加<br />

运<br />

节<br />

的<br />

数<br />

库<br />

节<br />

(mathematical library) standard 函<br />

ulp。 但<br />

(full<br />

误<br />

计<br />

。truncf()、ceilf()<br />

而<br />

。<br />

附 录 B 标 准 数 学 函 数<br />

B.1 节<br />

B.1 通 用 运 行 时 组 件<br />

中 的 函 数 仅 能 在 设 备 函 数 中 使 用<br />

各 函 数 在 设 备 上 执 行 时 的 误 差 范 围 。 当 函 数 在 宿 主 上 执 行 , 而 宿 主 并 未 提 供 此 函 数 时 , 误 差 范 围 同 样 适 用 。<br />

B.2 举 的 函 数 可 由 宿 主 和 设 备 函 数 使 用 , 但 列 中<br />

B.1.1<br />

单 精 度 浮 点 函 数<br />

和<br />

函<br />

。<br />

绍 <strong>CUDA</strong><br />

这 里 列 举 的 误 差 范 围 经 过 了 广 泛 的 测 试 , 但 并 非 详 尽 无 遗 , 所 以 很 难 保 证 正 确 无 误<br />

这 一 节 介<br />

行 时 库 支 持 的 所 有 数 学 标 准 库<br />

数 。 此 外 还 指 定 了<br />

可 映 射 到 一 条 指 令 。 均<br />

floorf() 也<br />

会<br />

指<br />

只<br />

和<br />

截 (FMAD),<br />

IEEE 和 乘 法 是 符 合 法 加<br />

0.5 此 误 差 最 多 为 因 ,<br />

在 设 备 上 , 编 译 器 往 往 将 其 整 合 为 一 个 单 独 的<br />

- 指 令 乘<br />

_fadd_rn() 法 的 中 间 结 果 。 可 通 过 使 用 乘 取<br />

_fmul_rn()<br />

数 来 避 免 这 样 的 整 合<br />

非 roundf()。<br />

x+y 0(IEEE-754 舍 错<br />

rintf() 单 精 度 浮 点 操 作 数 舍 入 为 整 型 , 而 使 结 果 为 单 精 度 浮 点 数 , 推 荐 的 方 法 是 使 用 将 要<br />

B.2 参 见 第 请 (<br />

)。<br />

原 因 在 于 roundf()<br />

8 到 设 备 上 的 一 个 射 映<br />

rintf() 列 , 而 序 令<br />

映 射 到 一 条 指 令<br />

x*y 0(IEEE-754 舍 时<br />

入 到 最 近 的 偶 数 ) 时 2( range))<br />

范 围 全<br />

x/y<br />

1/x 1 ( )<br />

1/sqrtf(x)<br />

2 ( )<br />

rsqrtf(x)<br />

sqrtf(x) 3 ( )<br />

cbrtf(x) 1 ( )<br />

hypotf(x,y) 3 ( )<br />

expf(x) 2 ( )<br />

exp2f(x) 2 ( )<br />

exp10f(x) 2 (<br />

expm1f(x) 1 (<br />

logf(x) 1 (<br />

log2f(x) 3 (<br />

log10f(x) 3 (<br />

log1pf(x) 2 (<br />

sinf(x) 2 (<br />

cosf(x) 2 (<br />

tanf(x) 4 (<br />

表 B-1.<br />

大 数 学 标 准 库 函 数 及 其 最 大 ULP<br />

误 差<br />

<strong>CUDA</strong> 误 差 表 示 为 正 确 舍 入 的 单 精 度 结 果 和 大 最<br />

ulp 返 回 的 结 果 之 间 以 数 函<br />

的 差 的 绝 对 值 。 算<br />

函 数<br />

大 最 大 ulp<br />

错 误<br />

FMAD 合 并 入 在 (<br />

外 ) 除<br />

FMAD 合 并 入 在 (<br />

外 ) 除<br />

60 <strong>CUDA</strong> 编<br />

) 围 范<br />

) 围 范<br />

) 围 范<br />

) 围 范<br />

2.0 南 , 版 本 指 程<br />

) 围 范<br />

)<br />

范 围 围 )<br />

) 围 范<br />

) 围 范


程 指 南 , 版<br />

内 间 外 距 全 范 围 sincosf(x,sptr,cptr) 2 (<br />

asinf(x) 4 ( )<br />

acosf(x) 3 ( )<br />

atanf(x) 2 ( )<br />

atan2f(y,x) 3 ( )<br />

sinhf(x) 3 ( )<br />

coshf(x) 2 ( )<br />

tanhf(x) 2 ( )<br />

asinhf(x) 3 ( )<br />

acoshf(x) 4 ( )<br />

atanhf(x) 3 ( )<br />

powf(x,y) 7 ( )<br />

erff(x) 4 ( )<br />

erfcf(x) 8 ( )<br />

lgammaf(x) 6 ( (outside interval)-10.001 ... -2.264;<br />

tgammaf(x) 11 ( )<br />

fmaf(x,y,z) 0 ( )<br />

frexpf(x,exp) 0 ( )<br />

ldexpf(x,exp) 0 ( )<br />

scalbnf(x,n) 0 ( )<br />

scalblnf(x,l) 0 ( )<br />

logbf(x) 0 ( )<br />

ilogbf(x) 0 ( )<br />

fmodf(x,y) 0 ( )<br />

remainderf(x,y) 0 ( )<br />

remquof(x,y,iptr) 0 ( )<br />

modff(x,iptr) 0 ( )<br />

fdimf(x,y) 0 ( )<br />

truncf(x) 0 ( )<br />

roundf(x) 0 ( )<br />

rintf(x) 0 ( )<br />

nearbyintf(x) 0 ( )<br />

ceilf(x) 0 ( )<br />

floorf(x) 0 ( )<br />

lrintf(x) 0 ( )<br />

lroundf(x) 0 ( )<br />

llrintf(x) 0 ( )<br />

llroundf(x) 0 ( )<br />

signbit(x)<br />

N/A<br />

isinf(x)<br />

N/A<br />

isnan(x)<br />

N/A<br />

isfinite(x)<br />

N/A<br />

copysignf(x,y)<br />

N/A<br />

fminf(x,y)<br />

N/A<br />

fmaxf(x,y)<br />

N/A<br />

fabsf(x)<br />

N/A<br />

nanf(cptr)<br />

N/A<br />

nextafterf(x,y)<br />

N/A<br />

) 更 大 距 间<br />

) 围 范<br />

<strong>CUDA</strong> 编<br />

61<br />

本 2.0


或<br />

会<br />

类<br />

数<br />

指<br />

库<br />

仅<br />

错<br />

计<br />

。Trunc()、ceil() 和<br />

B.1.2<br />

双 精 度 浮 点 函 数<br />

floor() 均<br />

面 列 举 的 误 差 仅 适 用 于 为 具 有 本 地 双 精 度 支 持 的 设 备 编 译 的 情 况 。 在 为 无 此 类 支 持 的 设 备 编 译 时 ( 如 计 双 而 原 因 在 映 射 到 一 条 指 令 下<br />

是 round()。<br />

的 差 的 绝 对 值 。 算<br />

算 能 力 为 1.2<br />

更 低 的 设 备 ),double<br />

将 默 认 地 降 低 为 float, 型<br />

度 数 学 函 数 将 映 射 为 其 单 精 度 版 本 。 精<br />

将 双 精 度 浮 点 操 作 数 舍 入 为 整 型 , 而 使 结 果 为 双 精 度 浮 点 数 , 推 荐 的 方 法 是 使 用 rint(), 要<br />

不<br />

B-2.<br />

到 设 备 上 的 一 可 映 射 到 一 条 指 令 。 表 映 射 函 数<br />

序 列 , 错 误 令 错 误 入 到 最 近 的 偶 数 )<br />

最 的 数 入 近 到 舍 ) 偶 围 范<br />

更 间 入 内 到 舍 最 近 的 偶 数 ) 间 外 距<br />

全<br />

x+y 0 (IEEE-754<br />

x*y 0 (IEEE-754<br />

x/y 0 (IEEE-754<br />

1/x 0 (IEEE-754<br />

sqrt(x) 0 (IEEE-754<br />

rsqrt(x) 1 ( )<br />

cbrt(x) 1 ( )<br />

hypot(x,y) 2 ( )<br />

exp(x) 1 ( )<br />

exp2(x) 1 ( )<br />

exp10(x) 1 ( )<br />

expm1(x) 1 ( )<br />

log(x) 1 ( )<br />

log2(x) 1 ( )<br />

log10(x) 1 ( )<br />

log1px(x) 1 ( )<br />

sin(x) 2 ( )<br />

cos(x) 2 ( )<br />

tan(x) 3 ( )<br />

sincos(x,sptr,cptr) 2 ( )<br />

asin(x) 2 ( )<br />

acos(x) 2 ( )<br />

atan(x) 3 ( )<br />

atan2(y,x) 3 ( )<br />

sinh(x) 1 ( )<br />

cosh(x) 1 ( )<br />

tanh(x) 1 ( )<br />

asinh(x) 2 ( )<br />

acosh(x) 2 ( )<br />

atanh(x) 2 (<br />

pow(x,y) 2 (<br />

erf(x) 2 (<br />

erfc(x) 6 (<br />

lgamma(x) 4 ( ... -2.2637;<br />

tgamma(x) 7 (<br />

fma(x,y,z) 0 (IEEE-754<br />

frexp(x,exp) 0 (<br />

ldexp(x,exp) 0 (<br />

) 大<br />

于 round()<br />

个 8<br />

而 rint()<br />

大 数 学 标 准 库 函 数 及 其 最 大 ULP<br />

<strong>CUDA</strong> 误 差 表 示 为 正 确 舍 入 的 双 精 度 结 果 和 大 最<br />

ulp 返 回 的 结 果 之 间 以 数 函<br />

大 最 大 ulp<br />

62 <strong>CUDA</strong> 编<br />

) 围 范<br />

) 围 范<br />

) 围 范<br />

2.0 南 , 版 本 指 程<br />

) 围 范<br />

距 -11.0001<br />

) 围 范<br />

) 围 范<br />

) 围 范


后<br />

后<br />

后<br />

后<br />

程 指 南 , 版<br />

和<br />

它 y),<br />

前<br />

。<br />

所 列 函 数 的 精 确 度 较 低 但 速 度 节<br />

范 全 围 scalbn(x,n) 0 (<br />

scalbln(x,l) 0 ( )<br />

logb(x) 0 ( )<br />

ilogb(x) 0 ( )<br />

fmod(x,y) 0 ( )<br />

remainder(x,y) 0 ( )<br />

remquo(x,y,iptr) 0 ( )<br />

modf(x,iptr) 0 ( )<br />

fdim(x,y) 0 ( )<br />

trunc(x) 0 ( )<br />

round(x) 0 ( )<br />

rint(x) 0 ( )<br />

nearbyint(x) 0 ( )<br />

ceil(x) 0 ( )<br />

floor(x) 0 ( )<br />

lrint(x) 0 ( )<br />

lround(x) 0 ( )<br />

llrint(x) 0 ( )<br />

llround(x) 0 ( )<br />

signbit(x)<br />

N/A<br />

isinf(x)<br />

N/A<br />

isnan(x)<br />

N/A<br />

isfinite(x)<br />

N/A<br />

copysign(x,y)<br />

N/A<br />

fmin(x,y)<br />

N/A<br />

fmax(x,y)<br />

N/A<br />

fabs(x)<br />

N/A<br />

nan(cptr)<br />

N/A<br />

nextafter(x,y)<br />

N/A<br />

) 围 范<br />

B.1.3<br />

整 型 函 数<br />

<strong>CUDA</strong> 运<br />

y)<br />

B.2 设 备 运 行 时 组 件<br />

们 可 映 射 到 设 备 上 的 一 条 指 令<br />

min(x, 库 支 持 整 型 时 行<br />

max(x,<br />

( 如 __sinf(x))。 缀<br />

用 _rn<br />

<strong>CUDA</strong> 编<br />

型 强 制 转 换 函 数 直 接 对 一 个 参<br />

63<br />

__ 的 版 本 ; 它 们 具 有 相 同 的 名 称 , 另 外 加 上 快 更<br />

B.1 节 列 举 了 仅 在 设 备 代 码 中 支 持 的 内 建 函 数 。 这 些 函 数 中 包 括 第 一 这<br />

__int_as_float(0xC0000000) 等<br />

等<br />

_ru 用 使<br />

舍 入 到 最 近 的 偶 数 模 式 操 作 ;<br />

上 正 ; 使<br />

的 函 数 将 使 用 向 下 舍 入 ( 向 负 无 穷 大 ) 模 式 。 不 同 于 将 一 种 类 型 转 换 为 另 一 种 类 型 的 类 型 转 换 函 数 ( 类 数 执 行 类 型 强 制 转 换 , 而 保 留 其 值 不 变 。 例 如 : 缀<br />

_rz 用 使<br />

的 函 数 将 使 用 向 零 方 向 舍 入 模 式 操 作 ; 缀<br />

本 2.0<br />

_rz 用 使<br />

如 _int2float_rn),<br />

于 -2,__float_as_int(1.0f)<br />

于 0x3f800000。


B.2.1<br />

单 精 度 浮 点 函 数<br />

__fadd_rn() __fmul_rn() FMAD 和 映 射 为 加 法 和 法 作 且 译 不 把 们 入 。 此 相 比 ,“*” 和 “+” 运 算 符 生 成 的 加 法 和 乘 法 一 般 都 将 被 并 入 FMAD。<br />

_fdividef(x, y) 2 126 < y < 2 128 ,__fdivedef(x, y)<br />

B-1 2<br />

普 通 浮 点 除 法 和 具 有 相 同 精 度 , 但 在 时 为 0,<br />

126 < y < 2 128 x<br />

__ fdivedf(x, y) 0<br />

而 普 通 除 法 将 在 表 列 举 的 精 确 度 内 提 供 正 确 。 同 样 , 在 时 , 如 果 是 无 穷 大 ,<br />

操 编 器 会<br />

__[u]mul24(x, y) x y 24 32 。x<br />

y 8<br />

他 并 中 与<br />

NaN(<br />

__[u]mulhi(x, y) x y 64 32<br />

的 结 果 ), 而 普 通 除 法 将 返 回 无 穷 大 。<br />

__[u]mul64hi(x, y) 64 x y 128 个 最 低 有 效 的 乘 积 , 提 供 个 最 低 有 效 位 的 结 果 和 的 个 最 高 有 效 位 将 被 忽 略 。 将<br />

64<br />

得<br />

__saturate(x)<br />

到<br />

x<br />

结<br />

0<br />

果<br />

x<br />

无<br />

1<br />

__[u]sad(x,<br />

穷<br />

y, z<br />

大<br />

x y<br />

以<br />

, 提 供 位 结 果 中 的 个 最 高 有 效 位 计 算 位 整 型 参 数 和 的 乘 积 , 提 供 位 结 果 中 的 个 最 高 有 效 位 。 将 在 小 于 时 0, 在 大 于 时 返 回 1, 否 则 返 回 x。 计<br />

__clz(x) x 31 0 0 32<br />

0<br />

算 整 型 参 数 和 的 乘 积<br />

型 参 数 z)(<br />

__clzll(x) 64 x 63 0 0 64<br />

整 型 参 数 与 的 差 绝 对 值 之 和 。<br />

0 从 最 高 有 效 位 ( 即 第 位 ) 开 始 的 连 续 位 的 数 量 , 介 于 和 之 间 ( 包<br />

__ffs(x) x x<br />

括 和 32)。 和<br />

0,_ffs()<br />

绝<br />

Linux<br />

对 差 之 和 ) 返 回 整 位 ( 即 第 ) 开 始 的 连 续 的 数 量 , 介 于 和 之 间 ( 包 括 和 64)。<br />

整 型 参 数 中 第 一 个 ( 最 低 有 效 ) 位 组 的 位 置 。 最 低 有 效 位 是 位 置 1。 如 果 为 将 返 回 0。 请 注 意 , 此 函 数 等 同 于 函 数 ffs。<br />

__ffsll(x) x x<br />

0,__ffsll() Linux 从 高<br />

一 个 ( 最 低 有 效 ) 位 组 的 位 置 。 最 低 有 效 位 是 位 置 1。 如 果 为 将 返 回 0。 请 注 意 , 此 函 数 等 同 于 函 数 ffsll。<br />

B-3 <strong>CUDA</strong><br />

__fadd_[rn,rz](x,y)<br />

IEEE<br />

__fmul_[rn,rz](x,y)<br />

IEEE<br />

__fdividef(x,y)<br />

表 运 行 时 库 支 持 的 单 精 度 浮 点 建 函 数 及 其 误 差 范 围<br />

y [2<br />

返 回 位 整 型 参 数 中 的 第 误 差 范 围<br />

符 合 -126 , 2 126 ] ulp 2.<br />

__expf(x)<br />

ulp<br />

2 + floor(abs(1.16 * 区 间 内 , 则 最 大 误 差 为 __exp10f(x)<br />

ulp<br />

2 + floor(abs(2.95 *<br />

函 数<br />

为<br />

x))。<br />

__logf(x)<br />

x [0.5, 2] 2 -21.41, ulp<br />

__log2f(x)<br />

x [0.5, 2] 2 ulp<br />

则 最 大<br />

最 大 误 差 -22,<br />

__log10f(x)<br />

x [0.5, 2] 2 ulp<br />

2。 否 -24,<br />

__sinf(x) x [-π, π] 2<br />

否 则 最 大 误 差 为 3。<br />

-21.41<br />

__cosf(x) x [-π, π] 2 -21.19<br />

__sincosf(x,sptr,cptr) sinf(x) cosf(x)<br />

__tanf(x)<br />

__sinf(x) * (1 /<br />

如 果 在 区 间 内 , 则 最 大 绝 对 误 差 为 , 否 则 更 大 。<br />

相 同 。 误 差 为 3。<br />

__powf(x, y)<br />

exp2f(y * 下 实 现 :<br />

__log2f(x))。<br />

__mul24(x,y)<br />

N/A<br />

__umul24(x,y)<br />

__cosf(x))。<br />

__mulhi(x,y)<br />

N/A<br />

以 自 承 继 和<br />

__umulhi(x,y)<br />

64 <strong>CUDA</strong> 2.0 本 版 , 南 指 程 编<br />


和<br />

映<br />

位<br />

位<br />

程 指 南 , 版<br />

的<br />

的<br />

的<br />

的 位 数 。<br />

算 。 与 此 相 比 ,“*” 运<br />

围<br />

__int_as_float(x)<br />

N/A<br />

__float_as_int(x)<br />

N/A<br />

__saturate(x)<br />

N/A<br />

__sad(x,y,z)<br />

__usad(x,y,z)<br />

N/A<br />

__clz(x)<br />

N/A<br />

__ffs(x)<br />

N/A<br />

__float2int_[rn,rz,ru,rd] N/A<br />

__float2uint_[rn,rz,ru,rd] N/A<br />

__int2float_[rn,rz,ru,rd] N/A<br />

__uint2float_[rn,rz,ru,rd] N/A<br />

B.2.2<br />

双 精 度 浮 点 函 数<br />

_dadd_rn()<br />

<strong>CUDA</strong> 运<br />

__dadd_[rn,rz,ru,rd](x,y)<br />

__dmul_[rn,rz,ru,rd](x,y)<br />

__fma_[rn,rz,ru,rd](x,y,z)<br />

__double2float_[rn,rz](x)<br />

__double2int_[rn,rz,ru,rd](x)<br />

__double2uint_[rn,rz,ru,rd](x)<br />

__double2ll_[rn,rz,ru,rd](x)<br />

__double2ull_[rn,rz,ru,rd](x)<br />

__int2double_rn(x)<br />

__uint2double_rn(x)<br />

__ll2double_[rn,rz,ru,rd](x)<br />

__ull2double_[rn,rz,ru,rd](x)<br />

__double_as_longlong(x)<br />

__longlong_as_double(x)<br />

__double2hiint(x)<br />

__double2loint(x)<br />

__hiloint2double(x, ys)<br />

函 数<br />

运 行 时 库 支 持 的 双 精 度 浮 点<br />

IEEE-compliant.<br />

IEEE-compliant.<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

IEEE<br />

时 库 支 持 的 双 精 度 浮 点 内 建 围 函 数 及 其 误 差 范 误 差 范 围 符 合 行 运<br />

_dmul_rn()<br />

FMAD 加 法 和 乘 法 运 算 , 且 编 译 器 不 会 把 他 们 并 入 为 射<br />

“+” 运 算 符 生 成 的 加 法 和 乘 法 一 般 都 将 被 并 和<br />

入 FMAD。<br />

表 B-4.<br />

B.2.3<br />

整 型 函 数<br />

_popc(x) 返<br />

_popcll(x) 返<br />

位 数<br />

整 型 参<br />

二 进 制 表 示 中 设 置<br />

数 x<br />

为 1<br />

<strong>CUDA</strong> 编<br />

65<br />

64 在 回<br />

32 在 回<br />

x 参 数 型 整<br />

1 制 表 示 中 设 置 为 进 二<br />

本 2.0


位<br />

位<br />

位<br />

处<br />

位<br />

或<br />

或<br />

。<br />

- val), 并<br />

附 录 C 原 子 函 数<br />

更 高 的 设 备 可 用<br />

C.1 数 学 函 数<br />

1.1 函 数 仅 可 用 于 设 备 函 数 之 中 , 仅 对 计 算 能 力 为 子 原<br />

C.1.1<br />

atomicAdd()<br />

64 共 享 存 储 器 和 作 操<br />

1.2 原 子 函 数 只 能 用 于 计 算 能 力 为 的 字<br />

int atomicAdd(int* address, int val);<br />

unsigned int atomicAdd(unsigned int* address,<br />

unsigned int val);<br />

unsigned long long int atomicAdd(unsigned long long int* address,<br />

unsigned long long int val);<br />

处<br />

位<br />

位<br />

高 的 设 备 。 更<br />

+ val), 并<br />

将 结 果 存 储<br />

计<br />

C.1.2<br />

atomicSub()<br />

int atomicSub(int* address, int val);<br />

unsigned int atomicSub(unsigned int* address,<br />

unsigned int val);<br />

。 字<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

或 64<br />

字 old,<br />

算 (old<br />

存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 在<br />

64 全 局 存 储 器 支 持 有 只<br />

C.1.3<br />

atomicExch()<br />

int atomicExch(int* address, int val);<br />

unsigned int atomicExch(unsigned int* address,<br />

计<br />

unsigned int val);<br />

unsigned long long int atomicExch(unsigned long long int* address,<br />

unsigned long long int val);<br />

float atomicExch(float* address, float val);<br />

处<br />

位<br />

位<br />

存<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

算 (old<br />

将 结 果 存 储 在 存 储 器 的<br />

同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。<br />

储 在 存 储 器 的 同 一 地<br />

并<br />

C.1.4<br />

atomicMin()<br />

66 <strong>CUDA</strong> 编<br />

读 取 位 于 全 局 或 共 享 存 储 器 中 地<br />

int atomicMin(int* address, int val);<br />

unsigned int atomicMin(unsigned int* address,<br />

unsigned int val);<br />

址 address<br />

的 32<br />

或 64<br />

字 old,<br />

将 val<br />

中 。 这 两 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 址<br />

64 全 局 存 储 器 支 持 有 只<br />

。 字<br />

2.0 南 , 版 本 指 程


位<br />

程 指 南 , 版<br />

处<br />

位<br />

计<br />

计<br />

计<br />

和<br />

和<br />

的<br />

的<br />

>= val) ? 0 : (old+1)),<br />

& val), 并<br />

C.1.5<br />

atomicMax()<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

int atomicMax(int* address, int val);<br />

unsigned int atomicMax(unsigned int* address,<br />

unsigned int val);<br />

位 处<br />

的 32<br />

字 old,<br />

算 old<br />

val<br />

存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 在<br />

最 小 值 , 并 将 结 果 存 储<br />

C.1.6<br />

atomicInc()<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

unsigned int atomicInc(unsigned int* address,<br />

unsigned int val);<br />

位 处<br />

算 old<br />

val<br />

最 大 值 , 并 将 结 果 存 储<br />

C.1.7<br />

atomicDec()<br />

存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 在<br />

unsigned int atomicDec(unsigned int* address,<br />

unsigned int val);<br />

位 处<br />

val : (old-1)), 并<br />

== 0) | (old > val)) ?<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

算 ((old<br />

将 结 果 存 储 在 存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 并<br />

C.1.8 atomicCAS()<br />

int atomicCAS(int* address, int compare, int val);<br />

unsigned int atomicCAS(unsigned int* address,<br />

unsigned int compare,<br />

unsigned int val);<br />

unsigned long long int atomicCAS(unsigned long long int* address,<br />

unsigned long long int compare,<br />

unsigned long long int val);<br />

位 位 处<br />

将 结 果 存 储 在 存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 计<br />

== compare ? val :<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

算 (((old<br />

回 old。 返<br />

C.2 位 逻 辑 函 数<br />

计<br />

比<br />

<strong>CUDA</strong> 编<br />

67<br />

将 结 果 存 储 在 存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 计<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

或 64<br />

字 old,<br />

算 (old<br />

C.2.1<br />

atomicAnd()<br />

并 较 并 交 换 )。<br />

old),<br />

结 果 存 储 在 存 储 器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old( 将<br />

64 全 局 存 储 器 支 持 有 只<br />

。 字<br />

int atomicAnd(int* address, int val);<br />

unsigned int atomicAnd(unsigned int* address,<br />

unsigned int val);<br />

位 处<br />

算 (old<br />

本 2.0<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

回 old。


计<br />

计<br />

| val), 并<br />

^ val), 并<br />

C.2.2<br />

atomicOr()<br />

int atomicOr(int* address, int val);<br />

unsigned int atomicOr(unsigned int* address,<br />

unsigned int val);<br />

位 处<br />

C.2.3<br />

atomicXor()<br />

int atomicXor(int* address, int val);<br />

unsigned int atomicXor(unsigned int* address,<br />

unsigned int val);<br />

位 处<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

算 (old<br />

器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 储<br />

将 结 果 存 储 在 存<br />

将 结 果 存 储 在 存<br />

器 的 同 一 地 址 中 。 这 三 项 操 作 在 一 次 原 子 事 务 中 执 行 。 该 函 数 将 返 回 old。 储<br />

address 位 于 全 局 或 共 享 存 储 器 中 地 址 取 读<br />

的 32<br />

字 old,<br />

算 (old<br />

68 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程


≤<br />

寻<br />

的<br />

×<br />

是<br />

×<br />

是<br />

节<br />

个<br />

个<br />

它<br />

:<br />

和<br />

展<br />

寻<br />

,x、y<br />

,x 将<br />

=<br />

、j = floor( y)、k floor(z)。 =<br />

,N =4。<br />

包<br />

即<br />

= Nxˆ、y = Myˆ、z = Lzˆ。<br />

个<br />

的<br />

1.0]( 请<br />

的<br />

进<br />

节<br />

拾 取 < 替 行<br />

)。<br />

的<br />

×<br />

个 第<br />

。x、y、z 继<br />

附 录 D 纹 理 拾 取<br />

4.3.4 节<br />

定 到 纹 理 参 考 的 纹 理 表 示 为 数 组 T, 包 含 针 对 一 维 纹 理 绑<br />

4.4.3 录 提 供 了 用 于 根 据 纹 理 参 考 的 不 同 属 性 计 算 第 附 本<br />

。<br />

的 N<br />

texel,<br />

N 对 二 维 纹 理 的 针 者<br />

M<br />

<br />

<br />

< 0,x 将<br />

效 寻 址 范 围 内 , 之 后 才 能 用 于 寻 归 一 化 的 有<br />

其<br />

绍 的 纹 理 函 数 的 返 回 值 的 公 式 ( 请 参 见 或 介<br />

T。 寻 址 模 式 指 定 了 如 何 将 超 出 范 围 的 纹 理 址<br />

= x-floor(x),floor(x) 是<br />

texel, 或 )。<br />

标 映 射 到 有 效 范 围 内 。 如 坐<br />

N 对 三 维 纹 理 的 针 者<br />

M<br />

L<br />

texel。<br />

x、y 用 纹 理 坐 标 使 将<br />

z<br />

T 坐 标 必 须 位 于 理 纹<br />

如<br />

有 效 寻 址 范 围 内<br />

果 x<br />

x 一 化 的 , 则 仅 支 持 调 整 寻 址 模 式 , 如 果 归 非<br />

x 将 则 0,<br />

为 0, 换<br />

大 整 最<br />

N 果 如<br />

则 替 换 为 N-1。 x,<br />

果 x<br />

和<br />

、yˆ 和 是<br />

在 clamp<br />

x 式 内 , 如 果 模 址<br />

换 为 0, 如 果 1≤ x, 则 替 换 替<br />

为 1-1/N;<br />

D.1 最 近 点 采 样<br />

。 在 下 面 的 内 容 中 数<br />

在 wrap<br />

址 模 式 中<br />

替 换 为 frac(x), 被<br />

中 frac(x)<br />

x 于 大 不<br />

<br />

z<br />

T 一 化 的 纹 理 坐 标 , 已 重 新 映 射 到 归 非<br />

对<br />

y) =<br />

j]<br />

xˆ 归 一 化 纹 理 坐 标 自 承<br />

zˆ,<br />

x<br />

对<br />

y, z) =<br />

j, k]<br />

= floor(x)<br />

对 于 整 型 纹 理 来 说 , 纹 理 拾 取 的 返 回 值 可 重 新 映 射<br />

这 种 过 滤 模 式 中 , 纹 理 拾 取 返 回 的 值 如 下 : 在<br />

tex(x) 一 维 纹 理 是 于 对<br />

T[i]<br />

参 见<br />

i 中 其<br />

tex(x, 维 纹 理 是 二 于<br />

T[i,<br />

图 F-1<br />

示 了 一 维 纹 理 的 最 近 点 采 样<br />

tex(x, 维 纹 理 是 三 于<br />

T[i,<br />

第 4.3.4.1<br />

到 [0.0,<br />

<strong>CUDA</strong> 编<br />

69<br />

的 一 维 纹 理 的 最 近 点 采 样 包<br />

包 含<br />

含 4<br />

texel<br />

2.0 南 , 版 本 指 程<br />

图 F-1.


展<br />

展<br />

位<br />

= 4。 位<br />

,N<br />

值<br />

β<br />

或<br />

的<br />

D.2 线 性 过 滤<br />

对<br />

<br />

<br />

+1, j +1]<br />

理 纹 维 一 于<br />

=<br />

种 仅 对 浮 点 纹 理 可 用 的 过 滤 模 式 中 , 纹 理 拾 取 的 返 回 值 如 下<br />

(1−α)T[i] +αT[i +1]<br />

β 这 在<br />

y) = (1−α )(1−<br />

j] +α<br />

+1, j] + (1−α)βT[i, j +1] +αβT[i<br />

:<br />

j = 中 其<br />

k =<br />

yB ) , β<br />

) , γ<br />

yB ) , yB =<br />

) , zB =<br />

0.5; −<br />

0.5。 −<br />

i = :<br />

tex(x)<br />

对 于 三 维 纹 理 是<br />

) , α<br />

) , xB =<br />

− 0.5;<br />

tex(x, 二 维 纹 理 是 于 对<br />

)T[i,<br />

(1−<br />

)T[i<br />

floor(xB<br />

= frac(xB<br />

x<br />

floor(<br />

= frac(<br />

y<br />

9 γ 存 储 在 和 α、β<br />

8 点 格 式 中 , 有 定 的<br />

fractional<br />

。<br />

floor(zB<br />

= frac(zB<br />

z<br />

图 F-2<br />

示 了 一 维 纹 理 的 最 近 点 采 样<br />

D.3 表 查 找<br />

压<br />

个<br />

的<br />

且<br />

可<br />

=<br />

−1]。<br />

, 其<br />

处<br />

R] 区<br />

图 F-2.<br />

压 缩 寻 址 模 式 中 有<br />

的 一 维 纹 理<br />

纹 理 滤 的 线 性 过 70 <strong>CUDA</strong><br />

来<br />

编<br />

维 纹 理 。 一<br />

有 压 缩 寻 址 模 式 中 有 4<br />

Texel<br />

滤<br />

现 为 示 了 利 用 纹 理 过 滤 来 实 现 表 查 找 , 其 实<br />

TL(x) 找 函 数 查 表<br />

= T[0]<br />

TL(R)<br />

T[N<br />

中 x<br />

于 [0,<br />

自 N=4<br />

TL(0) , 这 样 即 可 确 保 内 间<br />

R=1,<br />

图 F-3<br />

2.0 南 , 版 本 指 程<br />

中 R=4


程 指 南 , 版<br />

使 用 线 性 过 滤 的 一 维 表 查 找<br />

图 F-3.<br />

<strong>CUDA</strong> 编<br />

71<br />

本 2.0


不 设<br />

、Geforce、Tesla 和<br />

不<br />

都<br />

伟 峰 先 生 对 本 指 南 中 文 版 译 稿 全 文 进 行 了 审 校 , 在 此 表 示 衷 心 的 感 谢 。 刘<br />

<strong>NVIDIA</strong> Corporation 专<br />

Corporation 的<br />

。<strong>NVIDIA</strong> 注 意 : 样 ” 提 供 对 特 定 目 的 的 适 用 性 Corporation 的<br />

规 范 、 参 考 设 计 、 文 件 、 绘 图 、 诊 断 程 序 、 列 表 和 其 他 文 档 ( 统 称 为 “ 材 料 ”) 均 按 “ 原 对 此 材 料 提 供 任 何 明 示 或 暗 示 的 保 证 和 担 保 , 不 保 证 材 料 的 无 侵 害 性 、 适 销 性 或 针 计<br />

对<br />

NVDIA 有 所<br />

<strong>NVIDIA</strong>、<strong>NVIDIA</strong> 徽<br />

Corporation 的<br />

但 <strong>NVIDIA</strong><br />

公 司 或 产 品 名 称 可 能 是 其 对 应 公 司 的 商 标 。<br />

<strong>NVIDIA</strong><br />

们 尽 可 能 保 证 信 息 的 准 确 和 可 靠 。 为 使 用 此 类 信 息 的 后 果 承 担 责 任 , 也 为 使 用 此 类 信 息 可 能 导 致 的 侵 害 第 三 方 专 利 或 其 他 权 利 的 后 果 负 责 。 本 材 料 未 通 过 任 何 隐 含 的 方 式 或 其 他 方 式 授 予 利 或 权 利 权 的 许 可 本 文 档 提 到 的 规 范 可 能 随 时 更 改 , 恕 不 另 行 通 知 。 本 文 档 提 供 。<br />

是 最 新 内 容 , 取 代 之 前 提 供 的 所 有 信 息 。 若 无 明 确 书 面 许 可 , 不 得 我<br />

品 用 作 生 命 保 障 设 备 或 系 统 的 关 键 组 件 。<br />

商 标 产 的<br />

将 <strong>NVIDIA</strong><br />

© 2007-2008 <strong>NVIDIA</strong> Corporation. 保<br />

:Scalable Parallel Programming with <strong>CUDA</strong>, in ACM<br />

Queue, VOL 6, No. 2 (March/April 2008), © ACM, 2008. http://mags.acm.org/queue/20080304/?u1=texterity"<br />

版 权 留 所 有 权 利 。 本 文 档 整 合 了 早 先 一 份 资 料 的 部 分 内 容 致 谢<br />

标<br />

Quadro<br />

是 <strong>NVIDIA</strong><br />

商 标 或 注 册 商 标 。 其 他<br />

<strong>NVIDIA</strong> Corporation<br />

72 <strong>CUDA</strong> 编<br />

2.0 南 , 版 本 指 程

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!