
Amit Ben-Moshe
Amit Ben-Moshe 是 AMD 的技术主管和首席技术成员。他的帖子是他个人的观点,不一定代表 AMD 的立场、策略或观点。指向第三方网站的链接仅为方便起见,除非另有明确说明,否则 AMD 对这些链接网站的内容概不负责,也不暗示任何认可。
关于 CodeXL Analyzer CLI
CodeXL Analyzer CLI 是一款用于 OpenCL
内核、DirectX® 着色器和 OpenGL® 着色器的离线编译器和性能分析工具。使用 CodeXL Analyzer CLI,您可以独立于系统硬件,为各种 AMD GPU 和 APU 编译内核和着色器,并为每个目标平台生成 AMD ISA、中间语言和性能统计信息。
CodeXL Analyzer CLI 被图形工程师和并行计算应用程序开发者用于识别性能瓶颈和优化其代码。它还被用作 AMD 工具产品(如 CodeXL 的 Analyze 模式和 GPU PerfStudio 的 Shader Analyzer)的着色器编译和性能统计信息生成后端。
主要特性
- 编译 OpenCL 内核和 DirectX 或 OpenGL 着色器,以生成 AMD ISA 代码、中间语言代码、性能统计信息和程序二进制文件。
- 为各种 AMD GPU 和 APU 生成、二进制文件和性能统计信息,独立于您系统中实际安装的设备。
- 观察不同的优化和编译链如何影响内核和着色器的性能:32 位与 64 位、各种编译器优化、内核和着色器代码更改等等。
CodeXL Analyzer CLI 同时支持 Microsoft Windows® 和 Linux®。
启动 CodeXL Analyzer CLI
CodeXL Analyzer CLI 的命令由多个命令行开关组成,其中一些适用于所有平台(OpenCL、DirectX、OpenGL),而另一些则特定于平台。以下是适用于所有平台的主要命令选项列表
基本选项
| 命令行开关 | 描述 | 注释 |
| -s | 指定平台:“cl”代表 OpenCL,“hlsl”代表 DirectX,“glsl”代表 OpenGL | 每次调用处理一个平台 |
| -s | 显示所选平台的帮助菜单 | |
| -c | 生成输出的目标设备 | 可以多次出现;如果未出现,则默认以所有设备为目标 |
| -l | 列出支持的设备名称 | |
| –isa | 生成文本 ISA 代码并将结果保存到给定的输出完整路径 | Analyzer 会将设备名称连接到文件名,以区分不同设备的输出 |
| -a | 生成性能统计信息并将结果保存到给定的输出完整路径 | Analyzer 会将设备名称连接到文件名,以区分不同设备的输出 |
在接下来的部分中,我们将介绍特定平台的主要命令选项。我们将重点介绍最常用的命令,而不涵盖所有可用选项。有关所有可用选项的列表,您可以随时使用 –h 命令行开关。
OpenCL 特定选项
对于 OpenCL 内核,CodeXL Analyzer CLI 除了文本 ISA 和性能统计信息外,还可以编译高级源代码并提取 AMD IL 代码和编译后的二进制文件。以下是 OpenCL 内核的特定选项
| 命令行开关 | 描述 | 注释 |
| –il | 生成文本 AMD IL 代码并将结果保存到给定的输出文件(完整文件路径) | 输出文件名会更改以区分不同设备的输出 |
| -b | 将编译后的二进制文件保存到给定的输出文件(完整文件路径) | |
| –kernel | 为给定的内核生成输出 | 使用 –kernel all 来针对所有内核 |
DirectX 特定选项
对于 DirectX 着色器,CodeXL Analyzer CLI 除了文本 ISA 和性能统计信息外,还可以提取 DX ASM 代码。以下是 DirectX 着色器的特定选项
| 命令行开关 | 描述 | 注释 |
| -f | 目标入口点名称 | |
| -p | 着色器配置文件(例如 vs_5_0、ps_5_0 等) | |
| –DumpMSIntermediate | 将 DX ASM 代码保存到给定的输出完整路径 |
OpenGL 特定选项
对于 OpenGL,仅支持单个着色器源文件。
| 命令行开关 | 描述 | 注释 |
| -p | 指定着色器类型:Vertex、TessEval、Geometry、Fragment 和 compute | Analyzer 的“glsl”模式不支持 Tessellation control shaders |
注意:CodeXL Analyzer CLI 的“glsl”模式(仅接受单个着色器)已被弃用,未来版本将用新的 OpenGL 模式替换,该模式将允许编译和链接整个 OpenGL 程序,并生成更准确的 ISA、性能统计信息和每个阶段的二进制文件。
用法示例
让我们来看以下 .cl 文件(BinarySearch_Kernels.cl,摘自 AMD APP SDK)
__kernel voidbinarySearch( __global uint4 * outputArray,__const __global uint2 * sortedArray,const unsigned int findMe){ unsigned int tid = get_global_id(0); uint2 element = sortedArray[tid]; if((element.x > findMe) || (element.y < findMe)) { return; } else { outputArray[0].x = tid; outputArray[0].w = 1; }}
__kernel voidbinarySearch_mulkeys(__global int *keys,__global uint *_input,const unsigned int numKeys,__global int *_output){ int gid = get_global_id(0); int lBound = gid * 256; int uBound = lBound + 255;
for(int i = 0; i < numKeys; i++) { if(keys[i] >= _input[lBound] && keys[i] <=_input[uBound]) _output[i]=lBound; }}
__kernel voidbinarySearch_mulkeysConcurrent(__global uint *keys,__global uint *_input,const unsigned int inputSize,const unsigned int numSubdivisions,__global int *_output){ int lBound = (get_global_id(0) % numSubdivisions) * (inputSize / numSubdivisions); int uBound = lBound + inputSize / numSubdivisions; int myKey = keys[get_global_id(0) / numSubdivisions]; int mid;
while(uBound >= lBound) { mid = (lBound + uBound) / 2; if(_input[mid] == myKey) { _output[get_global_id(0) / numSubdivisions] = mid; return; } else if(_input[mid] > myKey) uBound = mid - 1; else lBound = mid + 1; }}