跳到主要内容

MUSA C++ 语言扩展

概述

MUSA C++ 扩展是 MCC 编译器为 MTGPU 编程提供的语言扩展。它保持了与标准 C++ 的兼容性,同时添加了用于表达并行计算的语法结构。

核心扩展内容

  • 函数限定符:__global__, __device__, __host__
  • 内存限定符:__shared__, __constant__, __managed__
  • 内置变量:threadIdx, blockIdx, gridDim, blockDim
  • Kernel 启动语法:<<<grid, block>>>

本文档详细介绍 MUSA C++ 扩展的语法和用法。


变量限定符

device 限定符

__device__ 限定符声明的函数在 MUSA 设备上执行:

__device__ float device_function(float x) {
return x * x + 1.0f;
}

host 限定符

__host__ 限定符声明的函数在 MUSA 主机上执行:

__host__ float host_function(float x) {
return std::sqrt(x);
}

global 限定符

__global__ 限定符声明从主机调用、在设备上执行的函数(核函数):

__global__ void vector_add_kernel(
const float *a,
const float *b,
float *c,
int n
) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) {
c[idx] = a[idx] + b[idx];
}
}

device host 组合

同时使用两个限定符可以使函数同时支持设备和主机:

__device__ __host__ float compatible_function(float x) {
return x * 2.0f;
}

内置变量

MCC 提供了预定义的内置变量:

线程索引

// 线程在块内的索引
threadIdx.x // 0 到 blockDim.x - 1
threadIdx.y // 0 到 blockDim.y - 1
threadIdx.z // 0 到 blockDim.z - 1

块索引

// 块在网格中的索引
blockIdx.x // 0 到 gridDim.x - 1
blockIdx.y // 0 到 gridDim.y - 1
blockIdx.z // 0 到 gridDim.z - 1

块维度

// 块的维度(线程数)
blockDim.x
blockDim.y
blockDim.z

网格维度

// 网格的维度(块数)
gridDim.x
gridDim.y
gridDim.z

Warp 信息

// 使用设备提供的实际 Warp 大小,不要硬编码产品或固定值
warpSize

内置函数概览

MUSA 提供丰富的设备端内置函数,详细说明请参阅 原子函数Warp 函数

同步函数

函数作用域说明
__syncthreads()线程块块内所有线程的同步屏障
__threadfence()设备级约束设备范围内的内存访问顺序
__threadfence_block()线程块确保块内所有内存写操作可见
__threadfence_system()系统级约束系统范围内的内存访问顺序
__syncwarp()线程束线程束级同步屏障

原子函数

函数说明
atomicAdd(), atomicSub()原子加减
atomicExch()原子交换
atomicInc(), atomicDec()原子递增递减
atomicAnd(), atomicOr(), atomicXor()原子位运算
atomicCAS()原子比较交换
备注

原子函数支持 _block_system 变体,分别用于块级和系统级作用域。

Warp 级函数

函数说明
__shfl_sync()Warp 内线程间数据交换
__all_sync(), __any_sync()Warp 投票
__ballot_sync()位选投票
__reduce_*_sync()Warp 归约操作

数学函数

// 标准精度
sin(x), cos(x), exp(x), log(x), sqrt(x)

// 快速版本(低精度,高性能)
__sinf(x), __cosf(x), __expf(x), __logf(x), __sqrtf(x)
函数类型精度性能适用场景
标准函数精确计算
快速函数性能敏感场景

核函数配置

执行配置

核函数启动使用 <<<grid, block, shared_mem, stream>>> 语法:

// grid: 网格维度(块数)
// block: 块维度(每块线程数)
// shared_mem: 动态共享内存大小(字节)
// stream: 执行流

kernel_name<<<grid_dim, block_dim, shared_mem, stream>>>(args);

示例

// 一维配置
int n = 1024;
int block_size = 256;
int grid_size = (n + block_size - 1) / block_size;
kernel<<<grid_size, block_size>>>(args);

// 二维配置(图像处理)
dim3 block(16, 16);
dim3 grid((width + 15) / 16, (height + 15) / 16);
kernel<<<grid, block>>>(args);

内存模型

MUSA 支持多种内存类型。本节介绍设备端代码(Device Code)中常用的存储空间和访问方式。

全局内存

// 在全局内存中声明变量
__device__ float global_array[1024];

// 动态分配全局内存(Runtime API)
float* d_ptr;
musaMalloc(&d_ptr, size);

共享内存

// 静态共享内存
__global__ void kernel1() {
__shared__ float shared_mem[256];
// 使用 shared_mem
}

// 动态共享内存(通过核函数配置传递)
__global__ void kernel2() {
extern __shared__ float shared_mem[];
// 使用 shared_mem
}

// 启动时指定大小
kernel2<<<grid, block, 256 * sizeof(float)>>>(args);

常量内存

// 声明常量内存
__constant__ float const_array[1024];

// 从主机初始化
musaMemcpyToSymbol(const_array, h_data, size);
备注

纹理内存和表面函数的创建、资源描述和生命周期由 Runtime API 管理。


编译

编译 MUSA C++ 程序时,显式指定已发布目标架构。当前示例使用 mp_31

mcc -mtgpu --offload-arch=mp_31 vector_add.mu -o vector_add

.mu 是 MUSA C++ 源文件后缀。使用模板、lambda 或 C++ 标准库组件时,可显式指定 C++ 标准:

mcc -mtgpu --offload-arch=mp_31 -std=c++14 kernel.mu -o app

编译或性能比较前,固定 SDK、驱动、编译器、目标设备、C++ 标准、优化选项和数值相关选项。对不满足目标架构、数据类型或形状条件的路径,保留普通 Device Code 回退路径,并以公开头文件和编译测试确认实际支持情况。

编译指示

循环展开

#pragma unroll
for (int i = 0; i < 8; i++) {
// 编译器展开循环,提高性能
}

强制内联

__forceinline__ float fast_add(float a, float b) {
return a + b;
}

错误处理

MUSA 使用 musaError_t 类型表示错误。错误枚举和数值应以 SDK 的 Runtime API 头文件为准,不要在应用文档中重声明或复制不完整的枚举。

错误处理示例

musaError_t err = musaMalloc(&ptr, size);
if (err != musaSuccess) {
fprintf(stderr, "Memory allocation failed: %d\n", err);
return -1;
}

扩展关键字总览

关键字描述
__device__设备函数
__host__主机函数
__global__核函数
__shared__共享内存
__constant__常量内存
__managed__统一内存
__restrict__指针非别名
__inline__内联函数
__noinline__不内联

相关文档