SIMT Built-In Keywords

Function Execution Space Qualifier

The function execution space qualifier indicates whether the function is executed on the host or device, and the space scope that can be called.

Table 1 Function execution space qualifiers

Function Execution Space Qualifier

Execution Space

Function Space Call Allowed

Host

Device

Host

Device

__host__, no qualifier

√

x

√

x

__aicore__

x

√

x

√

__global__

x

√

√

x

A function modified by __global__ is the entry of a kernel function and has the following restrictions:

Functions decorated with __aicore__ can be executed only on the device and can be called only by __global__ functions or other __aicore__ functions.

Functions decorated with __host__ can be called and executed only on the host.

Memory Space Qualifier

The memory space qualifier __ubuf__ is used to indicate dynamic and static memory. The size of the static memory is determined during compilation, and the size of the dynamic memory is determined during kernel function execution.

The current version does not support dynamic and static memory.

Built-in Variables

Currently, the following built-in variables of the dim3 structure are provided, which are available only on the device:

Currently, the following built-in variables of the int type are provided, which are available only on the device:

Built-in Data Types

Currently, a series of data types applicable to the device are provided, including scalars and short vectors. A short vector is a simple vector consisting of multiple elements.
Table 2 Scalar data types

Type

Data Type

Description

Size (Bit)

Value Range

Boolean

bool

Bool type, which occupies 8 bits. When all bits are 0, it represents false; any non-zero value represents true.

8

true, flase

Integer

uint8_t

unsigned char

8

[0, 255]

int8_t

signed char

8

[-128, 127]

uint16_t

unsigned short

16

[0, 65535]

int16_t

signed short

16

[-32768, 32767]

uint32_t

unsigned int

32

[0, 4294967295]

int32_t

signed int

32

[-2147483648, 2147483647]

uint64_t

unsigned long

64

[0, 18446744073709551615]

int64_t

signed long

64

[-9223372036854775808, 9223372036854775807]

Float

float8_e4m3_t

1-bit sign width, 4-bit exponent width, and 3-bit mantissa width

8

[26 - 29, 29 - 26]

float8_e5m2_t

1-bit sign width, 5-bit exponent width, and 2-bit mantissa width

8

[213 - 216, 216 - 213]

hifloat8_t

1-bit sign width, 2-bit point field width, and exponent and mantissa widths determined by the point field code

8

The point field code determines the data precision and value range.

half

1-bit sign width, 5-bit exponent width, and 10-bit mantissa width

16

[25 - 216, 216 - 25]

bfloat16_t

1-bit sign width, 8-bit exponent width, and 7-bit mantissa width

16

[2120 - 2128, 2128 - 2120]

float

1-bit sign width, 8-bit exponent width, and 23-bit mantissa width

32

[2104 - 2128, 2128 - 2104]

Short vector data types are classified into Vector X2 and Vector X4, indicating that a short vector variable has two and four elements, respectively. The currently supported types are as follows.

Element Data Type

Vector X2

Vector X4

unsigned char

uchar2

uchar4

signed char

char2

char4

unsigned short (16bit)

ushort2

ushort4

signed short (16bit)

short2

short4

unsigned int

uint2

uint4

signed int

int2

int4

Unsigned long integer (64 bit)

ulonglong2

ulonglong4

Signed long integer (64 bit)

longlong2

longlong4

Unsigned long integer (32 bit)

ulong2

ulong4

Signed long integer (32 bit)

long2

long4

Floating-point type, 1 sign bit, 2 exponent bits, and 1 mantissa bit

float4_e2m1x2_t

-

Floating-point type, 1 sign bit, 1 exponent bit, and 2 mantissa bits

float4_e1m2x2_t

-

Floating-point type, 1 sign bit, 4 exponent bits, and 3 mantissa bits

float8_e4m3x2_t

-

Floating-point type, 1 sign bit, 5 exponent bits, and 2 mantissa bits

float8_e5m2x2_t

-

Floating-point type (hif8)

hifloat8x2_t

-

Floating-point type, 1 sign bit, 5 exponent bits, and 10 mantissa bits

half2

-

Floating-point type, 1 sign bit, 8 exponent bits, and 7 mantissa bits

bfloat16x2_t

-

Floating-point type, 1 sign bit, 8 exponent bits, and 23 mantissa bits

float2

float4

Table 3 Short vector data types

Data Type

Memory Size (Bytes)

Address Alignment (Bytes)

char2, uchar2

2

2

char4, uchar4

4

4

short2, ushort2

4

4

short4, ushort4

8

8

int2, uint2

8

8

int4, uint4

16

16

long2, ulong2

8

8

long4, ulong4

16

16

longlong2, ulonglong2

16

16

longlong4, ulonglong4

32

32

float2

8

8

float4

16

16

float4_e2m1x2_t, float4_e1m2x2_t

1

1

float8_e4m3x2_t, float8_e5m2x2_t, hifloat8x2_t

2

2

half2, bfloat16x2_t

4

4

Operator

SIMT programming provides a series of operators for performing mathematical operations. The following table lists the supported operators.
Table 4 Operators supported by SIMT programming

Type

Operator

bool

int8_t/uint8_t/int16_t/uint16_t/int32_t/uint32_t/int64_t/uint64_t

half/bfloat16_t/float

half2/bfloat16x2_t

hifloat8_t

Arithmetic operator

+

x

√

√

√

x

-

x

√

√

√

x

*

x

√

√

√

x

/

x

√

√

√

x

%

x

√

x

x

x

++

x

√

√

√

x

--

x

√

√

√

x

- (inverted)

x

√

√

√

x

Comparison operator

<

x

√

√

x

x

<=

x

√

√

x

x

>

x

√

√

x

x

>=

x

√

√

x

x

==

x

√

√

x

x

!=

x

√

√

x

x

Bitwise operator

&

x

√

x

x

x

|

x

√

x

x

x

^

x

√

x

x

x

~

x

√

x

x

x

<<

x

√

x

x

x

>>

x

√

x

x

x

Logical operator

&&

√

√

√

x

x

||

√

√

√

x

x

!

√

√

√

x

x

Condition operator

a ? b : c

√

√

√

√

x

The following is an example of using operators:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Addition operation
res[idx] = x[idx] + y[idx]; 

// Inversion operation
x[idx] = (-x[idx]);

// Comparison operation
if (x[idx] > y[idx]) {
    res[idx] = x[idx];
} else {
    res[idx] = y[idx];
}

// Bitwise AND operation
res[idx] = x[idx] & y[idx];

// Logical OR operation
if (x[idx] || y[idx]) {
    res[idx] = 1;
}

// Condition operation
res[idx] = x[idx] > y[idx] ? x[idx] : y[idx];

Kernel Function Configuration

The execution configuration must be specified when a function modified by the __global__ qualifier is called. The execution configuration is inserted between the parameter list enclosed in parentheses following the function name, for example:

1
<<<grid_dim, block_dim, dynamic_mem_size, stream>>>

Where:

The following example shows how to declare and call a kernel function:
1
2
3
4
// Declaration
__global__ void add_custom(float* x, float* y, float* z, uint64_t total_length);
// Call
add_custom<<<block_num, thread_num_per_block, dyn_ubuf_size, stream>>>(x, y, z, 1024);

Before executing the function, the preceding configuration parameters are validated. If grid_dim or block_dim exceeds the maximum size allowed by the device, or dynamic_smem_bytes exceeds the remaining available shared memory after static memory allocation, the function will fail to execute.

When multiple threads are executed concurrently, using fewer registers per thread allows more threads and thread blocks to reside in the Ascend AI Processor, thereby improving performance. Therefore, the compiler uses heuristic algorithms to minimize register spilling and the number of instructions, while also reducing the number of used registers. Applications can use the __launch_bounds__() qualifier in the __global__ function definition to restrict the launch bounds, providing additional information to assist the compiler in optimizing this process. This is an optional configuration.