3. 接口介绍
3.1. 访存函数
3.1.1. __builtin_mxc_ldg_*_predicator
功能描述
从全局内存中加载数据。相比普通加载操作,该操作的活跃线程掩码exec_mask来自于函数参数中两个数值的比较结果。
接口声明
u1u8 __builtin_mxc_ldg_b8_predicator(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v1u16 __builtin_mxc_ldg_b16_predicator(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v1u32 __builtin_mxc_ldg_b32_predicator(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v2i16 __builtin_mxc_ldg_b32_predicator_v2s(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v2i16 __builtin_mxc_ldg_b32_predicator_v2h(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4i8 __builtin_mxc_ldg_b32_predicator_v4c(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v2u32 __builtin_mxc_ldg_b64_predicator(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4i16 __builtin_mxc_ldg_b64_predicator_v4s(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4f16 __builtin_mxc_ldg_b64_predicator_v4h(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v8i8 __builtin_mxc_ldg_b64_predicator_v8c(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4u32 __builtin_mxc_ldg_b128_predicator(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v8i16 __builtin_mxc_ldg_b128_predicator_v8s(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v8f16 __builtin_mxc_ldg_b128_predicator_v8h(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v16i8 __builtin_mxc_ldg_b128_predicator_v16c(void *global_addr, int offset, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
参数
名称 |
描述 |
|---|---|
return_value |
从内容中载入的值 |
global_addr |
全局内存地址 |
offset |
全局内存偏移 |
ret0_en |
当参数为true时,非活跃线程返回0 |
saddr_flag |
暗示编译器使用streg(single thread register) 存储全局内存地址 |
pred_neg |
当参数为true时,将活跃线程掩码取反 |
is_async |
当参数为true时,用户需要主动插入arrive操作进行访存同步,而非依赖编译器处理。请谨慎使用 |
cmp_opnd1 |
用于生成活跃线程掩码的第一个比较操作数 |
cmp_opnd2 |
用于生成活跃线程掩码的第二个比较操作数 |
cmp_flag |
可用的比较操作。取值范围及含义如下: MACA_ICMP_EQ: exec_mask = (cmp_operand1 == cmp_operand2) MACA_ICMP_NE: exec_mask = (cmp_operand1 != cmp_operand2) MACA_ICMP_UGT: exec_mask = (cmp_operand1 > cmp_operand2), usigned MACA_ICMP_UGE: exec_mask = (cmp_operand1 >= cmp_operand2), usigned MACA_ICMP_ULT: exec_mask = (cmp_operand1 < cmp_operand2) usigned MACA_ICMP_ULE: exec_mask = (cmp_operand1 <= cmp_operand2), usigned MACA_ICMP_SGT: exec_mask = (cmp_operand1 > cmp_operand2), signed MACA_ICMP_SGE: exec_mask = (cmp_operand1 >= cmp_operand2), signed MACA_ICMP_SLT: exec_mask = (cmp_operand1 < cmp_operand2), signed MACA_ICMP_SLE: exec_mask = (cmp_operand1 <= cmp_operand2), signed |
代码示例
using v1u32 = __NATIVE_VECTOR__(1, unsigned int);
__device__ v1u32 test_builtin_mxc_ldg_b32_predicator(int *ptr, int a) {
v1u32 val = __builtin_mxc_ldg_b32_predicator(ptr, 0, false, false, false, false, threadIdx.x, a, MACA_ICMP_ULT);
return val;
}
3.1.2. __builtin_mxc_stg_*_predicator
功能描述
将数据写入全局内存。相比普通写入操作,该操作的活跃线程掩码exec_mask来自于函数参数中两个数值的比较结果。
接口声明
void __builtin_mxc_stg_b8_predicator(int *global_addr, int offset, v1u8 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b16_predicator(int *global_addr, int offset, v1u16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b32_predicator(int *global_addr, int offset, v1u32 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b32_predicator_v2s(int *global_addr, int offset, v2i16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b32_predicator_v2h(int *global_addr, int offset, v2f16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b32_predicator_v4c(int *global_addr, int offset, v4i8 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b64_predicator(int *global_addr, int offset, v2u32 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b64_predicator_v4s(int *global_addr, int offset, v4i16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b64_predicator_v4h(int *global_addr, int offset, v4f16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b64_predicator_v8c(int *global_addr, int offset, v8i8 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b128_predicator(int *global_addr, int offset, v4u32 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b128_predicator_v8s(int *global_addr, int offset, v8i16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b128_predicator_v8h(int *global_addr, int offset, v8f16 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
void __builtin_mxc_stg_b128_predicator_v16c(int *global_addr, int offset, v16i8 data, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
参数
名称 |
描述 |
|---|---|
global_addr |
全局内存地址 |
offset |
全局内存偏移 |
data |
需要被写入全局内存的数据 |
saddr_flag |
暗示编译器使用streg(single thread register) 存储全局内存地址 |
pred_neg |
当参数为true时,将活跃线程掩码取反 |
is_async |
当参数为true时,用户需要主动插入arrive操作进行访存同步,而非依赖编译器处理。请谨慎使用 |
cmp_operand1 |
用于生成活跃线程掩码的第一个比较操作数 |
cmp_operand2 |
用于生成活跃线程掩码的第二个比较操作数 |
cmp_flag |
可用的比较操作。取值范围及含义如下: MACA_ICMP_EQ: exec_mask = (cmp_operand1 == cmp_operand2) MACA_ICMP_NE: exec_mask = (cmp_operand1 != cmp_operand2) MACA_ICMP_UGT: exec_mask = (cmp_operand1 > cmp_operand2), usigned MACA_ICMP_UGE: exec_mask = (cmp_operand1 >= cmp_operand2), usigned MACA_ICMP_ULT: exec_mask = (cmp_operand1 < cmp_operand2) usigned MACA_ICMP_ULE: exec_mask = (cmp_operand1 <= cmp_operand2), usigned MACA_ICMP_SGT: exec_mask = (cmp_operand1 > cmp_operand2), signed MACA_ICMP_SGE: exec_mask = (cmp_operand1 >= cmp_operand2), signed MACA_ICMP_SLT: exec_mask = (cmp_operand1 < cmp_operand2), signed MACA_ICMP_SLE: exec_mask = (cmp_operand1 <= cmp_operand2), signed |
代码示例
__global__ void test_builtin_mxc_stg_b32_predicator(void *ptr, unsigned val, int a) {
__builtin_mxc_stg_b32_predicator(ptr, 0, val, false, false, false, threadIdx.x, a, MACA_ICMP_ULT);
}
3.1.3. __builtin_mxc_ldg_*_predicator_ret
功能描述
从全局内存中加载数据。相比普通加载操作,该操作的活跃线程掩码来自于函数参数中两个数值的比较结果。相比__builtin_mxc_ldg_*_predicator,该操作可以指定非活跃线程的返回值。
接口声明
v1u8 __builtin_mxc_ldg_b8_predicator_ret(void *global_addr, int offset, v1u8 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v1u16 __builtin_mxc_ldg_b16_predicator_ret(void *global_addr, int offset, v1u16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v1u32 __builtin_mxc_ldg_b32_predicator_ret(void *global_addr, int offset, v1u32 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v2i16 __builtin_mxc_ldg_b32_predicator_v2s_ret(void *global_addr, int offset, v2i16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v2f16 __builtin_mxc_ldg_b32_predicator_v2h_ret(void *global_addr, int offset, v2f16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4i8 __builtin_mxc_ldg_b32_predicator_v4c_ret(void *global_addr, int offset, v4i8 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v2u32 __builtin_mxc_ldg_b64_predicator_ret(void *global_addr, int offset, v2u32 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4i16 __builtin_mxc_ldg_b64_predicator_v4s_ret(void *global_addr, int offset, v4i16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4f16 __builtin_mxc_ldg_b64_predicator_v4h_ret(void *global_addr, int offset, v4f16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v8i8 __builtin_mxc_ldg_b64_predicator_v8c_ret(void *global_addr, int offset, v8i8 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v4u32 __builtin_mxc_ldg_b128_predicator_ret(void *global_addr, int offset, v4u32 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v8i16 __builtin_mxc_ldg_b128_predicator_v8s_ret(void *global_addr, int offset, v8i16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v8f16 __builtin_mxc_ldg_b128_predicator_v8h_ret(void *global_addr, int offset, v8f16 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
v16i8 __builtin_mxc_ldg_b128_predicator_v16c_ret(void *global_addr, int offset, v16i8 ret_val, bool saddr_flag, bool pred_neg, bool is_async, unsigned cmp_operand1, unsigned cmp_operand2, int cmp_flag);
参数
名称 |
描述 |
|---|---|
return_value |
从内容中载入的值 |
global_addr |
全局内存地址 |
offset |
全局内存偏移 |
ret_val |
非活跃线程的返回值 |
saddr_flag |
暗示编译器使用streg(single thread register) 存储全局内存地址 |
pred_neg |
当参数为true时,将活跃线程掩码取反 |
is_async |
当参数为true时,用户需要主动插入arrive操作进行访存同步,而非依赖编译器处理。请谨慎使用 |
cmp_operand1 |
用于生成活跃线程掩码的第一个比较操作数 |
cmp_operand2 |
用于生成活跃线程掩码的第二个比较操作数 |
cmp_flag |
可用的比较操作。取值范围及含义如下: MACA_ICMP_EQ: exec_mask = (cmp_operand1 == cmp_operand2) MACA_ICMP_NE: exec_mask = (cmp_operand1 != cmp_operand2) MACA_ICMP_UGT: exec_mask = (cmp_operand1 > cmp_operand2), usigned MACA_ICMP_UGE: exec_mask = (cmp_operand1 >= cmp_operand2), usigned MACA_ICMP_ULT: exec_mask = (cmp_operand1 < cmp_operand2) usigned MACA_ICMP_ULE: exec_mask = (cmp_operand1 <= cmp_operand2), usigned MACA_ICMP_SGT: exec_mask = (cmp_operand1 > cmp_operand2), signed MACA_ICMP_SGE: exec_mask = (cmp_operand1 >= cmp_operand2), signed MACA_ICMP_SLT: exec_mask = (cmp_operand1 < cmp_operand2), signed MACA_ICMP_SLE: exec_mask = (cmp_operand1 <= cmp_operand2), signed |
代码示例
__device__ v1u32 test_builtin_mxc_ldg_b32_predicator_ret(int *ptr, v1u32 ret_val, int a) {
v1u32 val = __builtin_mxc_ldg_b32_predicator_ret(ptr, 0, ret_val, false, false, false, threadIdx.x, a, MACA_ICMP_ULT);
return val;
}
3.1.4. __builtin_mxc_ldg_*_bsm
功能描述
从全局内存中加载数据并写入共享内存。
接口声明
v1u32 __builtin_mxc_ldg_b32_bsm(__shared__ void *shared_addr, void *global_addr, int offset, size_t mask, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async);
v2u32 __builtin_mxc_ldg_b64_bsm(__shared__ void *shared_addr, void *global_addr, int offset, size_t mask, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async);
v4u32 __builtin_mxc_ldg_b128_bsm(__shared__ void *shared_addr, void *global_addr, int offset, size_t mask, bool ret0_en, bool saddr_flag, bool pred_neg, bool is_async);
参数
名称 |
描述 |
|---|---|
return_value |
用于传递给特定同步函数__builtin_mxc_barrier_and_wait*的标志位,非实际的加载数据。如果使用__syncthreads()来保证该函数执行完成,则返回值可省略 |
shared_addr |
写入数据的共享内存地址 |
global_addr |
加载数据的全局内存地址 |
offset |
共享内存地址和全局内存地址共用的常量偏移 |
mask |
只能填-1。当前无实际意义 |
ret0_en |
当参数为true时,非活跃线程返回0 |
saddr_flag |
暗示编译器使用streg(single thread register) 存储全局内存地址 |
pred_neg |
当参数为true时,将活跃线程掩码取反 |
is_async |
当参数为true时,用户需要主动插入arrive操作进行访存同步,而非依赖编译器处理。请谨慎使用 |
代码示例
__device__ void test_builtin_mxc_ldg_b32_bsm(int *ptr) {
extern __shared__ int shared_ptr[];
v1u32 ret_flag = __builtin_mxc_ldg_b32_bsm(shared_ptr, ptr, 0, -1, false, false, false, false);
__builtin_mxc_barrier_and_wait1(1, ret_flag);
}
// or
__device__ void test_builtin_mxc_ldg_b32_bsm(int *ptr) {
extern __shared__ int shared_ptr[];
__builtin_mxc_ldg_b32_bsm(shared_ptr, ptr, 0, -1, false, false, false, false);
__syncthreads();
// then load data from shared_ptr
}
3.1.6. __builtin_mxc_arrive
功能描述
内存栅栏,支持全局内存和共享内存的处理。当访存操作队列中未完成的操作数量达到或低于目标值时,代码才可以继续向后执行。
接口声明
void __builtin_mxc_arrive(unsigned flag);
参数
名称 |
描述 |
|---|---|
flag |
flag中不同bit的含义如下: flag[5:0] = gvm_cnt,全局内存队列剩余未完成数量的目标值 flag[6] = gvm_cnt_enable,为1时使能全局内存栅栏 flag[10:7] = bsm_cnt ,共享内存队列剩余未完成数量的目标值 flag[12] = bsm_cnt_enable ,为1时使能共享内存栅栏 当flag为0时,表示必须等待前面所有全局内存和共享内存操作执行完成。 |
代码示例
__global__ void test_builtin_mxc_arrive_global(int *ptr, int *data) {
int val = ptr[0];
__builtin_mxc_arrive(64); // (1 << 6)
data[0] = val;
}
__global__ void test_builtin_mxc_arrive_shared(int *data) {
extern __shared__ int shared_ptr[];
int shared_val = shared_ptr[threadIdx.x];
__builtin_mxc_arrive(4096); // (1 << 12);
data[0] = shared_val;
}
3.1.7. __builtin_mxc_arrive_gvmcnt
功能描述
全局内存栅栏。当全局内存访问操作队列中未完成的操作数量达到或低于目标值时,代码才可以继续向后执行。
接口声明
void __builtin_mxc_arrive_gvmcnt(unsigned gvmcnt);
参数
名称 |
描述 |
|---|---|
gvmcnt |
全局内存队列中剩余未完成数量的目标值。有效值范围:0~63 |
代码示例
__global__ void test_builtin_mxc_arrive_gvmcnt(int *ptr, int *data) {
int val = ptr[0];
__builtin_mxc_arrive_gvmcnt(0);
data[0] = val;
}
3.1.8. __builtin_mxc_arrive_bsmcnt
功能描述
共享内存栅栏。当共享内存访问操作队列中未完成的操作数量达到或低于目标值时,代码才可以继续向后执行。
接口声明
void __builtin_mxc_arrive_bsmcnt(unsigned bsmcnt);
参数
名称 |
描述 |
|---|---|
bsmcnt |
全局内存队列中剩余未完成数量的目标值。有效值范围:0~15 |
代码示例
__global__ void test_builtin_mxc_arrive_bsmcnt(int *data) {
__shared__ int ptr[];
int val = ptr[0];
__builtin_mxc_arrive_bsmcnt(0);
data[0] = val;
}
3.1.9. __builtin_mxc_barrier_ex
功能描述
指令屏障。block内所有线程到执行到该位置后才可以继续向后执行。
接口声明
void __builtin_mxc_barrier_ex(int flag);
参数
参数 |
描述 |
|---|---|
flag |
当值为0时,产生指令屏障和内存栅栏。编译器会根据代码中内存访问操作类型自动添加相应的内存栅栏。 当值为1时,产生指令屏障和共享内存栅栏。编译器只有当代码中存在共享内存访问操作时才会自动添加共享内存栅栏。 当值为2时,仅产生指令屏障。编译器不会自动插入任何的内存栅栏。 当值为3时。不会产生指令屏障和内存栅栏。此时该函数仅用于阻止一些编译优化行为,不会产生任何的同步操作。 |
代码示例
__global__ void test_swap_warp_data(int *data) {
__shared__ int sharedData[128];
int id = threadIdx.x + blockIdx.x + blockDim.x;
int warpId = id / 64;
int laneId = threadIdx.x % 64;
sharedData[id] = data[id];
// Swap data by shared memory. So barrier_shared is enough.
__builtin_mxc_barrier_ex(1);
int targetWarpId = warpId ^ 1;
int targetId = targetWarpId * 64 + laneId;
int val = sharedData[targetId];
data[id] = val;
}
3.1.10. __builtin_mxc_barrier_and_wait*
功能描述
内存栅栏。该函数只与__builtin_mxc_ldg_*_bsm配合使用,可以实现针对全局内存到共享内存加载操作的局部等待,从而在代码中构建更加高效灵活的数据访问与计算流水线。
接口声明
void __builtin_mxc_barrier_and_wait1(int scope, v1u32 ret_flag); // Used for 32bit load
void __builtin_mxc_barrier_and_wait2(int scope, v2u32 ret_flag); // Used for 64bit load
void __builtin_mxc_barrier_and_wait4(int scope, v4u32 ret_flag); // Used for 128bit load
参数
名称 |
描述 |
|---|---|
scop |
值为0时,仅有内存栅栏语义。当共享内存数据不存在跨warp共享时使用 值为1时,同时具备内存栅栏和指令屏障语义,功能与__syncthreads()相同。当共享内存数据存在跨warp共享时使用 |
ret_flag |
配对的__builtin_mxc_ldg_*_bsm的返回值,用来建立两个函数间的use-def链 |
代码示例
__device__ void test_builtin_mxc_ldg_b32_bsm(int *ptr) {
extern __shared__ int shared_ptr[];
v1u32 ret_flag = __builtin_mxc_ldg_b32_bsm(shared_ptr, ptr, 0, -1, false, false, false, false);
__builtin_mxc_barrier_and_wait1(1, ret_flag);
}
__device__ void test_builtin_mxc_ldg_b64_bsm(long *ptr) {
extern __shared__ long shared_ptr[];
v2u32 ret_flag = __builtin_mxc_ldg_b64_bsm(shared_ptr, ptr, 0, -1, false, false, false, false);
__builtin_mxc_barrier_and_wait2(0, ret_flag);
}
// Pseudo code to build software memory and compute pipeline.
__global__ void test1(..) {
...
__builtin_mxc_ldg_b64_bsm(shared_ptr1, ptr1, 0, -1, false, false, false, false);
__builtin_mxc_ldg_b64_bsm(shared_ptr2, ptr2, 0, -1, false, false, false, false);
__syncthreads(); // wait all memcpy from global to shared at the same time.
compute();
...
}
__global__ void test2(..) {
...
v2u32 ret_flag1 = __builtin_mxc_ldg_b64_bsm(shared_ptr1, ptr1, 0, -1, false, false, false, false);
v2u32 ret_flag2 = __builtin_mxc_ldg_b64_bsm(shared_ptr2, ptr2, 0, -1, false, false, false, false);
__builtin_mxc_barrier_and_wait2(0, ret_flag1); // only wait first memcpy
compute1();
__builtin_mxc_barrier_and_wait2(0, ret_flag2); // wait second memcpy
compute2();
...
}
3.2. 比较函数
3.2.1. __builtin_mxc_uicmp*
功能描述
32或64位无符号整数比较运算。函数产生一个64bit结果,每个bit表示当前warp内相应线程的比较结果。
接口声明
uint64_t __builtin_mxc_uicmp(unsigned int src0, unsigned int src1, int ICMP_OP);
uint64_t __builtin_mxc_uicmpl(uint64_t src0, uint64_t src1, int ICMP_OP);
参数
名称 |
描述 |
|---|---|
src0 |
左操作数 |
src1 |
右操作数 |
ICMP_OP |
运算符枚举值。取值范围如下: MACA_ICMP_EQ:等于 MACA_ICMP_NE:不等于 MACA_ICMP_UGT:无符号大于 MACA_ICMP_UGE:无符号大于等于 MACA_ICMP_ULT:无符号小于 MACA_ICMP_ULE:无符号小于等于 MACA_ICMP_SGT:有符号大于 MACA_ICMP_SGE:有符号大于等于 MACA_ICMP_SLT:有符号小于 MACA_ICMP_SLE:有符号小于等于 |
代码示例
__global__ void test_mxc_uicmp(uint64_t& res, uint64_t& lres, unsigned int a, unsigned int b, uint64_t x, uint64_t y) {
res = __builtin_mxc_uicmp(a, b, MACA_ICMP_EQ);
lres = __builtin_mxc_uicmpl(x, y, MACA_ICMP_NE);
}
3.2.2. __builtin_mxc_sicmp*
功能描述
32或64位有符号整数比较运算。函数产生一个64bit结果,每个bit表示当前warp内相应线程的比较结果。
接口声明
uint64_t __builtin_mxc_sicmp(int src0, int src1, int ICMP_OP);
uint64_t __builtin_mxc_sicmpl(long src0, long src1, int ICMP_OP);
参数
参考__builtin_mxc_uicmp*
代码示例
__global__ void test_mxc_sicmp(uint64_t& res, uint64_t& lres, int a, int b, long x, long y) {
res = __builtin_mxc_sicmp(a, b, MACA_ICMP_EQ);
lres = __builtin_mxc_sicmpl(x, y, MACA_ICMP_NE);
}
3.2.3. __builtin_mxc_fcmp*
功能描述
浮点比较运算。函数产生一个64bit结果,每个bit表示当前warp内相应线程的比较结果。
接口声明
uint64_t __builtin_mxc_fcmp(double src0, double src1, int fcmp_op);
uint64_t __builtin_mxc_fcmpf(float src0, float src1, int fcmp_op);
uint64_t __builtin_mxc_fcmph(_Float16 src0, _Float16 src1, int fcmp_op);
参数
名称 |
描述 |
|---|---|
src0 |
左操作数 |
src1 |
右操作数 |
ICMP_OP |
运算符枚举值。取值范围如下: CMP_EQ:等于 CMP_LT:小于 CMP_LE:小于等于 CMP_GT:大于 CMP_GE:大于等于 CMP_NEQ:不等于 CMP_O:有序比较,当两个操作数均不是NaN时返回1 CMP_U:无序比较,当两个操作数任意一个为NaN时返回1 |
代码示例
__global__ void test_mxc_fcmp(uint64_t& dres, uint64_t& fres, uint64_t& hres,
double da, double db, float fa, float fb, _Float16 ha, _Float16 hb) {
dres= __builtin_mxc_fcmp(da, db, 1);
fres = __builtin_mxc_fcmpf(fa, fb, 2);
hres = __builtin_mxc_fcmph(ha, hb, 3);
}
3.3. 类型转换函数
3.3.1. __builtin_mxc_cvt_f32totf32
架构支持限制
offload arch需要大于等于xcore1500。例如–offload-arch=xcore1500、–offload-arch=xcore1520等。
功能描述
将float类型数据转换为tf32类型.
接口声明
float __builtin_mxc_cvt_f32totf32(float);
代码示例
__global__ void test_cvt_f32totf32(float *in, float *out) {
int tid = threadIdx.x;
out[tid] = __builtin_mxc_cvt_f32totf32(in[tid]);
}
3.3.2. __builtin_mxc_cvt_pk_f32tou8
功能描述
将一个float类型的数据转换为8bit无符号整数,并将该8bit无符号整数替换到特定数据的指定字节位置.
接口声明
unsigned int __builtin_mxc_cvt_pk_f32tou8(float src0, unsigned int src1, unsigned int src2);
参数
名称 |
描述 |
|---|---|
return_value |
返回值 |
src0 |
待转换的浮点数据 |
src1 |
转换后数据插入位置的索引 |
src2 |
被替换局部数据的值 |
代码示例
__global__ void test(int *out, float a, float b, float c, float d) {
out[0] = __builtin_mxc_cvt_pk_f32tou8(a, 0, out[0]);
out[0] = __builtin_mxc_cvt_pk_f32tou8(b, 1, out[0]);
out[0] = __builtin_mxc_cvt_pk_f32tou8(c, 2, out[0]);
out[0] = __builtin_mxc_cvt_pk_f32tou8(d, 3, out[0]);
}
3.3.3. __builtin_mxc_b*_cast_to_f32
功能描述
将输入数据的某个字节以无符号8bit整数数值格式转换为float类型。
接口声明
float __builtin_mxc_b0_cast_to_f32(int S0); // convert S0.u[7:0] to float
float __builtin_mxc_b1_cast_to_f32(int S0); // convert S0.u[15:8] to float
float __builtin_mxc_b2_cast_to_f32(int S0); // convert S0.u[23:16] to float
float __builtin_mxc_b3_cast_to_f32(int S0); // convert S0.u[31:24] to float
代码示例
__global__ void test_byte_to_float(int* in, float* out){
out[0] = __builtin_mxc_b0_cast_to_f32(in[0]);
out[1] = __builtin_mxc_b1_cast_to_f32(in[0]);
out[2] = __builtin_mxc_b2_cast_to_f32(in[0]);
out[3] = __builtin_mxc_b3_cast_to_f32(in[0]);
}
3.4. 混洗函数
3.4.1. __builtin_mxc_mov_shfl
功能描述
一个warp中64个线程,每16个连续线程叫做一个row,分别为row0(thread 0~15)、row1(thread 16~31)、row2(thread 32~47)和row3(thread 48~63)。___builtin_mxc_mov_shfl_ 函数分别在每个row内完成16个线程间的数据混洗。
接口声明
int __builtin_mxc_mov_shfl(int val, int mode, int rmsk, int bmsk, int bc);
参数
名称 |
描述 |
|---|---|
dest |
返回值 |
src |
输入数据 |
mode |
混洗模式。取值范围及对应操作如下: 0x000-0x0FF: Quad Permutation 0x101-0x10F: Row Shift Left 0x111-0x11F: Row Shift Right 0x121-0x12F: Row Rotate Right 0x140: Row Mirror 0x150-0x15f: Row Broadcast |
RMSK |
row mask。每个bit表示相应的row是否执行此次混洗。 if (!(rmsk & 0x1)) row0 are disabled if (!(rmsk & 0x2)) row1 are disabled if (!(rmsk & 0x4)) row2 are disabled if (!(rmsk & 0x8)) row3 are disabled |
BMSK |
if (!(bmsk & 0x1)) lanes[0:3, 16:19, 32:35, 48:51] are disabled if (!(bmsk & 0x2)) lanes[4:7, 20:23, 36:39, 52:55] are disabled if (!(bmsk & 0x4)) lanes[8:11, 24:27, 40:43, 56:59] are disabled if (!(bmsk & 0x8)) lanes[12:15, 28:31, 44:47, 60:63] are disabled |
BC |
如果BC为0,则索引计算结果越界的线程将写0 如果BC为1,则索引计算结果越界的线程值不变 |
算法
Row Broadcast
将某个特定线程的值广播到同一个row内的所有其他线程。
for n in (1..64) dest.thread[n] = src.thread[(n&0x30)+ mode[3:0]]
Quad Permutation
将一个row内的16个线程划分为4个连续的4线程区间,在每一个区间内完成给定规则的混洗操作。
for n in (1..64) dest.thread[n] = src.thread[(n&0x3c)+mode[n%4*2+1:n%4*2]]
Row Rotate Right
在一个row内的16个线程间进行循环右移。
for n in (1..64) If((n&0xf) >= mode[3:0]) { dest.thread[n] = src.thread[n-mode[3:0]]; } else { dest.thread[n] = src.thread[n+16-mode[3:0]]; }
Row Shift Left
在一个row内的16个线程间进行左移。
for n in (1..64) If((n&0xf) < (16-mode[3:0])) { dest.thread[n] = src.thread[n+mode[3:0]]; } else { if BC == 0: dest.thread[n] = 0 else: do nothing }
Row Shift Right
在一个row内的16个线程间进行右移。
for n in (1..64) If((n&0xf) >= mode[3:0]) { dest.thread[n] = src.thread[n-mode[3:0]]; } else { if BC == 0: dest.thread[n] = 0 else: do nothing }
Row Mirror
在一个row内的16个线程间进行镜像变换。
for n in (1..64) dest.thread[n] = src.thread[(n^0xf)].
代码示例
__device__ int test_mxc_mov_shfl(int val) {
// Reverse every 16 threads.
return __builtin_mxc_mov_shfl(val, 0x140, 0xf, 0xf, false);
}
3.4.2. __builtin_mxc_update_shfl
功能描述
功能与__builtin_mxc_mov_shfl类似,不同之处在于__builtin_mxc_update_shfl在线程索引计算结果越界时可以指定返回值。
接口声明
int __builtin_mxc_update_shlf(int old_val, int src, int mode, int rmsk, int bmsk, int bc);
参数
名称 |
描述 |
|---|---|
dest |
返回值 |
old_val |
线程索引计算结果越界且BC为1时的返回值 |
src |
输入数据 |
mode |
混洗模式。取值范围及对应操作如下: 0x000-0x0FF: Quad Permutation 0x101-0x10F: Row Shift Left 0x111-0x11F: Row Shift Right 0x121-0x12F: Row Rotate Right 0x140: Row Mirror 0x150-0x15f: Row Broadcast |
RMSK |
row mask。每个bit表示相应的row是否执行此次混洗。 if (!(rmsk & 0x1)) row0 are disabled if (!(rmsk & 0x2)) row1 are disabled if (!(rmsk & 0x4)) row2 are disabled if (!(rmsk & 0x8)) row3 are disabled |
BMSK |
if (!(bmsk & 0x1)) lanes[0:3, 16:19, 32:35, 48:51] are disabled if (!(bmsk & 0x2)) lanes[4:7, 20:23, 36:39, 52:55] are disabled if (!(bmsk & 0x4)) lanes[8:11, 24:27, 40:43, 56:59] are disabled if (!(bmsk & 0x8)) lanes[12:15, 28:31, 44:47, 60:63] are disabled |
BC |
如果BC为0,则索引计算结果越界的线程将写0 如果BC为1,则索引计算结果越界的线程将写old_val |
Algorithm
see __builtin_mxc_mov_shfl
代码示例
__device__ int test_mxc_mov_shfl(int val) {
// Left shift every 16 threads, out of range return 100.
return __builtin_mxc_update_shfl(100, val, 0x108, 0xf, 0xf, true);
}
3.4.3. __builtin_mxc_bsm_bpermute
功能描述
warp内所有64个thread间的数据混洗。遍历返回值的所有线程,根据混洗规则参数选择输入数据特定线程的值写到返回值中。
接口声明
int __builtin_mxc_bsm_bpermute(int index, int data)
参数
名称 |
描述 |
|---|---|
dest |
返回值 |
index |
混洗规则,用法见算法描述 |
data |
输入数据 |
算法
for n in 0..63 //thread index
dest[n] = data[floor(index[n] / 4) % 64]
代码示例
__device__ int test_mxc_bsm_bpermute(int index, int data) {
// index[0:63] = {256, 254, ... 4,0}
// It will reverse the data of threads 0 to 63.
return __builtin_mxc_bsm_bpermute(index, data);
}
3.4.4. __builtin_mxc_bsm_permute
功能描述
warp内所有64个thread间的数据混洗。遍历输入数据的所有线程,根据混洗规则参数将输入数据写到返回值的特定线程中。
接口声明
int __builtin_mxc_bsm_permute(int index, int data)
参数
名称 |
描述 |
|---|---|
dest |
返回值 |
index |
混洗规则,用法见算法描述 |
data |
输入数据 |
算法
for n in 0..63 //thread index
dest[floor(index[n] / 4) % 64] = data[n]
代码示例
__device__ int test_mxc_bsm_permute(int index, int data) {
// index[0:63] = {256, 254, ... 4,0}
// It will reverse the data of threads 0 to 63.
return __builtin_mxc_bsm_permute(index, data);
}
3.4.5. __builtin_mxc_byte_perm
功能描述
线程内两个32bit数据的字节混洗,返回一个新的32bit数据
接口声明
unsigned int __builtin_mxc_byte_perm(unsigned int s0, unsigned int s1, unsigned perm);
参数
名称 |
描述 |
|---|---|
dest |
dest[31:24] = byte_permute({s0,s1}, perm[31:24]) dest[23:16] = byte_permute({s0,s1}, perm[23:16]) dest[15:8] = byte_permute({s0,s1}, perm[15:8]) dest[7:0] = = byte_permute({s0,s1}, perm[7:0]) |
s0 |
参与混洗的高32bit数据 |
s1 |
参与混洗的低32bit数据 |
perm |
混洗规则,用法见算法描述 |
算法
uint8_t byte_permute(uint8_t in[8], uint8_t sel) {
if(sel>=13) then return 0xff;
elseif(sel==12) then return 0x00;
elseif(sel==11) then return in[7][7] * 0xff;
elseif(sel==10) then return in[5][7] * 0xff;
elseif(sel==9) then return in[3][7] * 0xff;
elseif(sel==8) then return in[1][7] * 0xff;
else then return in[sel];
}
dest[31:24] = byte_permute({s0,s1}, perm[31:24]);
dest[23:16] = byte_permute({s0,s1}, perm[23:16]);
dest[15:8] = byte_permute({s0,s1}, perm[15:8]);
dest[7:0] = byte_permute({s0,s1}, perm[7:0]);
代码示例
__device__ int test_mxc_byte_reverse(unsigned int data) {
return __builtin_mxc_byte_perm(data, data, 0x04050607);
}
3.5. 浮点乘加函数
3.5.1. __builtin_mxc_pk_fma_f32
功能描述
单精度浮点向量fused multiply add。
接口声明
v2f32 __builtin_mxc_pk_fma_f32(v2f32 a, v2f32 b, v2f32 c);
代码示例
using v2f32 = __NATIVE_VECTOR__(2, float);
__global__ void test_mxc_pk_fma_f32(v2f32 *d, v2f32 *a, v2f32 *b, v2f32 *c) {
d[0] = __builtin_mxc_pk_fma_f32(a[0], b[0], c[0]);
}
3.5.2. __builtin_mxc_pk_fma_bf16
架构支持限制
offload arch需要大于等于xcore1500。例如–offload-arch=xcore1500、–offload-arch=xcore1520等。
功能描述
bf16类型向量fused multiply add。
接口声明
v2f16 __builtin_mxc_pk_fma_bf16(v2f16 a, v2f16 b, v2f16 c);
代码示例
using v2f16 = __NATIVE_VECTOR__(2, _Float16);
__global__ void test_mxc_pk_fma_bf16(v2f16 *d, v2f16 *a, v2f16 *b, v2f16 *c) {
d[0] = __builtin_mxc_pk_fma_bf16(a[0], b[0], c[0]);
}
3.5.3. __builtin_mxc_pk_fma_f16
架构支持限制
offload arch需要大于等于xcore1500。例如–offload-arch=xcore1500、–offload-arch=xcore1520等。
功能描述
fp16浮点向量fused multiply add。
接口声明
v2f16 __builtin_mxc_pk_fma_bf16(v2f16 a, v2f16 b, v2f16 c);
代码示例
using v2f16 = __NATIVE_VECTOR__(2, _Float16);
__global__ void test_mxc_pk_fma_f16(v2f16 *d, v2f16 *a, v2f16 *b, f2f16 *c) {
d[0] = __builtin_mxc_pk_fma_f16(a[0], b[0], c[0]);
}
3.5.4. __builtin_mxc_fma_bf16
架构支持限制
offload arch需要大于等于xcore1500。例如–offload-arch=xcore1500、–offload-arch=xcore1520等。
功能描述
bf16类型标量fused multiply add。
接口声明
_Float16 __builtin_mxc_fma_bf16(_Float16 a, _Float16 b, _Float16 c);
代码示例
__global__ void test_mxc_fma_bf16(_Float16 *d, _Float16 *a, _Float16 *b, _Float16 *c) {
d[0] = __builtin_mxc_fma_bf16(a[0], b[0], c[0]);
}
3.6. 矩阵乘加函数
3.6.1. __builtin_mxc_mma_16x16x16f16
功能描述
f16类型矩阵乘加函数 : D = A * B + C.
接口声明
v4f32 __builtin_mxc_mma_16x16x16f16(v4f16 a, v4f16 b, v4f32 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为float的16x16输出矩阵 |
a |
元素类型为f16的16x16输入矩阵 |
b |
元素类型为f16的16x16输入矩阵 |
c |
元素类型为float的16x16输入矩阵 |
代码示例
using v4f16 = __NATIVE_VECTOR__(4, _Float16);
using v4f32 = __NATIVE_VECTOR__(4, float);
__device__ v4f32 test_builtin_mxc_mma_16x16x16f16(v4f16 a, v4f16 b, v4f32 c) {
v4f32 d = __builtin_mxc_mma_16x16x16f16(a, b, c);
return d;
}
3.6.2. __builtin_mxc_mma_16x16x4f32
功能描述
float类型矩阵乘加函数 : D = A * B + C.
接口声明
v4f32 __builtin_mxc_mma_16x16x4f32(float a, float b, v4f32 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为float的16x16输出矩阵 |
a |
元素类型为float的16x4输入矩阵 |
b |
元素类型为float的4x16输入矩阵 |
c |
元素类型为float的16x16输入矩阵 |
代码示例
using v4f32 = __NATIVE_VECTOR__(4, float);
__device__ v4f32 test_builtin_mxc_mma_16x16x4f32(float a, float b, v4f32 c) {
v4f32 d = __builtin_mxc_mma_16x16x4f32(a, b, c);
return d;
}
3.6.3. __builtin_mxc_mma_16x16x16i8
架构支持限制
offload arch需要小于xcore1500。例如–offload-arch=xcore1000、–offload-arch=xcore1080等。
功能描述
int8类型矩阵乘加函数 : D = A * B + C.
接口声明
v4i32 __builtin_mxc_mma_16x16x16i8(int a, int b, v4i32 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为int32的16x16输出矩阵 |
a |
元素类型为int8的16x16输入矩阵 |
b |
元素类型为int8的16x16输入矩阵 |
c |
元素类型为int32的16x16输入矩阵 |
代码示例
using v4i32 = __NATIVE_VECTOR__(4, int);
__device__ v4i32 test_builtin_mxc_mma_16x16x16i8(int a, int b, v4i32 c) {
v4i32 d = __builtin_mxc_mma_16x16x16i8(a, b, c);
return d;
}
3.6.4. __builtin_mxc_mma_16x16x32i8
架构支持限制
offload arch需要大于等于xcore1500。例如–offload-arch=xcore1500、–offload-arch=xcore1520等。
功能描述
int8 type matrix mult-add : D = A * B + C.
接口声明
v4i32 __builtin_mxc_mma_16x16x32i8(v2i32 a, v2i32 b, v4i32 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为int32的16x16输出矩阵 |
a |
元素类型为int8的16x32输入矩阵 |
b |
元素类型为int8的32x16输入矩阵 |
c |
元素类型为int32的16x16输入矩阵 |
代码示例
using v4i32 = __NATIVE_VECTOR__(4, int);
using v2i32 = __NATIVE_VECTOR__(2, int);
__device__ v4i32 test_builtin_mxc_mma_16x16x16i8(v2i32 a, v2i32 b, v4i32 c) {
v4i32 d = __builtin_mxc_mma_16x16x32i8(a, b, c);
return d;
}
3.6.5. __builtin_mxc_mma_16x16x16bf16
功能描述
bf16类型矩阵乘加函数 : D = A * B + C.
接口声明
v4f32 __builtin_mxc_mma_16x16x16bf16(v4f16 a, v4f16 b, v4f32 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为float的16x16输出矩阵 |
a |
元素类型为bf16的16x16输入矩阵 |
b |
元素类型为bf16的16x16输入矩阵 |
c |
元素类型为float的16x16输入矩阵 |
代码示例
using v4f16 = __NATIVE_VECTOR__(4, _Float16);
using v4f32 = __NATIVE_VECTOR__(4, float);
__device__ v4f32 test_builtin_mxc_mma_16x16x16bf16(v4f16 a, v4f16 b, v4f32 c) {
v4f32 d = __builtin_mxc_mma_16x16x16bf16(a, b, c);
return d;
}
3.6.6. __builtin_mxc_mma_16x16x4f64
功能描述
double类型矩阵乘加函数 : D = A * B + C.
接口声明
v4f64 __builtin_mxc_mma_16x16x4f64(double a, double b, v4f64 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为double的16x16输出矩阵 |
a |
元素类型为double的16x4输入矩阵 |
b |
元素类型为double的4x16输入矩阵 |
c |
元素类型为double的16x16输入矩阵 |
代码示例
using v4f64 = __NATIVE_VECTOR__(4, double);
__device__ v4f64 test_builtin_mxc_mma_16x16x4f64(double A, double B, v4f64 C) {
v4f64 D = __builtin_mxc_mma_16x16x4f64(A, B, C);
return D;
}
3.6.7. __builtin_mxc_mma_16x16x8tf32
功能描述
tf32类型矩阵乘加函数 : D = A * B + C.
接口声明
v4f32 __builtin_mxc_mma_16x16x8tf32(v2f32 a, v2f32 b, v4f32 c);
参数
名称 |
描述 |
|---|---|
return_value |
元素类型为tf32的16x16输出矩阵 |
a |
元素类型为tf32的16x8输入矩阵 |
b |
元素类型为tf32的8x16输入矩阵 |
c |
元素类型为tf32的16x16输入矩阵 |
代码示例
using v4f32 = __NATIVE_VECTOR__(4, float);
using v2f32 = __NATIVE_VECTOR__(2, float);
__device__ v4f32 test_builtin_mxc_mma_16x16x8tf32(v2f32 A, v2f32 B, v4f32 C) {
v4f32 D = __builtin_mxc_mma_16x16x8tf32(A, B, C);
return D;
}
3.7. 常用计算函数
3.7.1. __builtin_mxc_mad_wide_i32/u32
功能描述
整数乘加。其中乘法操作数宽度为32bit,而累加操作数宽度为64bit。
接口声明
int64_t __builtin_mxc_mad_wide_i32(int a, int b, int64_t c);
uint64_t __builtin_mxc_mad_wide_u32(unsigned int a, unsigned int b, uint64_t c);
参数
名称 |
描述 |
|---|---|
return_value |
64bit返回值 |
a |
32bit乘法操作数 |
b |
32bit乘法操作数 |
c |
64bit累加操作数 |
代码示例
__global__ void test_mxc_madi32(int a,int b,int64_t c,int64_t* d) {
d[0]=__builtin_mxc_mad_wide_i32(a,b,c);
}
__global__ void test_mxc_madu32(unsigned int a,unsigned int b,uint64_t c,uint64_t* d) {
d[0]=__builtin_mxc_mad_wide_u32(a,b,c);
}
3.7.2. __builtin_mxc_pk_mul_f32
功能描述
单精度浮点向量乘法。 d[0] = a[0] * b[0] d[1] = a[1] * b[1]
接口声明
v2f32 __builtin_mxc_pk_mul_f32(v2f32 a, v2f32 b);
代码示例
typedef __NATIVE_VECTOR__(2, float) v2f32;
__global__ void pkFmulKernel(v2f32* input, v2f32* output, size_t size) {
int idx = threadIdx.x;
output[idx] = __builtin_mxc_pk_mul_f32(input[idx], output[idx]);
}
3.7.3. __builtin_mxc_pk_add_f32
功能描述
单精度浮点向量加法。 d[0] = a[0] + b[0] d[1] = a[1] + b[1]
接口声明
v2f32 __builtin_mxc_pk_add_f32(v2f32 a, v2f32 b);
代码示例
typedef __NATIVE_VECTOR__(2, float) v2f32;
__global__ void pkFmulKernel(v2f32* input, v2f32* output) {
int idx = threadIdx.x;
output[idx] = __builtin_mxc_pk_add_f32(input[idx], output[idx]);
}
3.7.4. __builtin_mxc_ubfe
功能描述 无符号位域提取。
接口声明
unsigned int __builtin_mxc_ubfe(unsigned int data, unsigned int field_offset, unsigned int field_width);
参数
名称 |
描述 |
|---|---|
return_value |
返回值 |
data |
输入数据 |
field_offset |
要提取的位域的起始位置 |
field_width |
要提取的位域的宽度 |
算法
return_value = (data >> field_offset[4:0]) & ((1 << field_width[4:0]) - 1)
代码示例
__global__ static void test_ubfe(unsigned int *res, unsigned int *src, unsigned int *offset, unsigned int *field) {
unsigned int id = threadIdx.x;
res[id] = __builtin_mxc_ubfe(src[id], offset[id], field[id]);
}
3.7.5. __builtin_mxc_sbfe
功能描述
有符号位域提取。
接口声明
int __builtin_mxc_sbfe(unsigned int data, unsigned int field_offset, unsigned int field_width);
参数
名称 |
描述 |
|---|---|
return_value |
返回值 |
data |
输入数据 |
field_offset |
要提取的位域的起始位置 |
field_width |
要提取的位域的宽度 |
算法
return_value = signext((data >> field_offset[4:0]) & ((1 << field_width[4:0]) - 1));
代码示例
__global__ static void test_sbfe(int *res, unsigned int *src, unsigned int *offset, unsigned int *field) {
unsigned int id = threadIdx.x;
res[id] = __builtin_mxc_sbfe(src[id], offset[id], field[id]);
}
3.7.6. __builtin_mxc_alignbit
功能描述
漏斗移位。
接口声明
unsigned int __builtin_mxc_alignbit(unsigned int a, unsigned int b, unsigned int shift);
参数
名称 |
描述 |
|---|---|
return_value |
返回值 |
a |
移位数据的高32bit |
b |
移位数据的低32bit |
shift |
移位位数 |
算法
return_value = ({a,b} >> shift[4:0]) & 0xffffffff;
代码示例
__global__ void test_alignbit_if_else(unsigned int *res) {
if (__lane_id() & 0x1) {
res[__lane_id()] = __builtin_mxc_alignbit(2, 1, 8);
} else {
res[__lane_id()] = __builtin_mxc_alignbit(2, 1, 4);
}
}
3.7.7. __builtin_mxc_cos*
功能描述
float和fp16类型的正弦函数。
接口声明
float __builtin_mxc_cosf(float);
_Float16 __builtin_mxc_cosh(_Float16);
3.7.8. __builtin_mxc_sin*
功能描述
float和fp16类型的余弦函数。
接口声明
float __builtin_mxc_sinf(float);
_Float16 __builtin_mxc_sinh(_Float16);
3.7.9. __builtin_mxc_rcp*
功能描述
float和fp16类型的倒数运算。
接口声明
float __builtin_mxc_rcpf(float);
_Float16 __builtin_mxc_rcph(_Float16);
代码示例
__global__ void test_rcp(float * fres, float* fin, _Float16 *hres, _Float16 *hin) {
unsigned int id = threadIdx.x;
fres[id] = __builtin_mxc_rcpf(fin[id]);
hres[id] = __builtin_mxc_rcph(hin[id]);
}
3.7.10. __builtin_mxc_sqrt*
功能描述
float和fp16类型的平方根运算
接口声明
float __builtin_mxc_sqrtf(float src);
_Float16 __builtin_mxc_sqrth(_Float16 src);
代码示例
__global__ void test_sqrt(float * fres, float* fin, _Float16 *hres, _Float16 *hin) {
unsigned int id = threadIdx.x;
fres[id] = __builtin_mxc_sqrtf(fin[id]);
hres[id] = __builtin_mxc_sqrth(hin[id]);
}
3.7.11. __builtin_mxc_rsq*
功能描述
float和fp16类型的平方根倒数运算:1.0/sqrt(x)。
接口声明
float __builtin_mxc_rsqf(float src);
_Float16 __builtin_mxc_rsqh(_Float16 src);
代码示例
__device__ float test_mxc_rsq(float a) {
return __builtin_mxc_rsqf(a);
}
3.7.12. __builtin_mxc_log_clampf
功能描述
以2为底的对数运算。结果限制在[0,1]区间,当结果小于0时返回0,当结果大于1时返回1。
接口声明
float __builtin_mxc_log_clampf(float);
代码示例
__global__ void test_mxc_log_clampf(float& fres, float& f1) {
fres = __builtin_mxc_log_clampf(f1);
}
3.8. 其他
3.8.1. __builtin_mxc_get_time
功能描述
返回当前时刻的64bit时间戳。
接口声明
int64_t __builtin_mxc_get_time();
代码示例
__device__ int64_t test_mxc_get_time() {
return __builtin_mxc_get_time();
}
3.8.2. __builtin_mxc_read_xmsk
功能描述
获取当前位置的线程活跃掩码。
接口声明
int64_t __builtin_mxc_read_xmsk();
代码示例
__device__ unsigned test_mxc_read_xmsk() {
return __builtin_mxc_read_xmsk();
}
3.8.3. __builtin_mxc_readfirstlane
功能描述
获取输入数据的第一个活跃线程中的数据,如果没有活跃线程则返回线程0的数据。例如,当线程活跃掩码为 0xffffffff00000000时,返回线程32中的值。
接口声明
int __builtin_mxc_readfirstlane(int data)
代码示例
__global__ void test_builtin_mxc_readfirstlane(int *output, int *input) {
int tid = blockDim.x * blockIdx.x + threadIdx.x;
int tmp;
// thread 32 ~ 63 is active.
if (tid > 31 && tid < 64) {
// return input[32].
tmp = __builtin_mxc_readfirstlane(input[tid]);
}
output[0] = tmp;
}
3.8.4. __builtin_mxc_readlane
功能描述
获取输入数据的指定线程中的数据。
接口声明
int __builtin_mxc_readlane(int data, int thread)
参数
名字 |
描述 |
|---|---|
return_value |
返回值 |
data |
输入数据 |
thread |
线程索引 |
代码示例
__device__ int test_mxc_readlane(int data, int thread) {
return __builtin_mxc_readlane(data, thread);
}
3.8.5. __builtin_mxc_writelane
功能描述
向输入数据的指定线程中写入新值。
接口声明
int __builtin_mxc_writelane(int val, int lane, int old_data)
参数
名字 |
描述 |
|---|---|
val |
要写入的新值 |
thread |
线程索引 |
old_data |
被修改的旧值 |
代码示例
__device__ int test_write_lane(int old_data) {
int ret_val = __builtin_mxc_writelane(10, 0, old_data);
return ret_val;
}
3.8.6. __builtin_mxc_nop
功能描述
插入一定数量的空操作。
接口声明
int __builtin_mxc_nop(int n)
参数
名字 |
描述 |
|---|---|
n |
空操作数量。每个空操作等于4拍。 |
代码示例
__device__ void test_mxc_nop() {
__builtin_mxc_nop(32); // wait for 128 cycles
return;
}