昇腾社区首页
中文
注册

全局变量

Host侧的全局变量与C++语言的全局变量特性相同,本节介绍的全局变量特指Device侧支持的全局变量。

Device侧的全局变量必须定义在命名空间作用域或者顶层作用域。由于异构结构的存在,用于区分Device侧和Host侧全局变量,所有Device侧的全局变量都需要关键字__gm__修饰。

__gm__ int g_device;                  //device side global variable 
int g_host;                           //host side global variable

全局变量的代码示例如下:

// built-in type global variable 
__gm__ bool bool_noinit; 
__gm__ int8_t int8_t_init = -8; 
__gm__ int32_t int32_t_arr_a[3] = {-321, -322}; 
__gm__ int64_t int64_t_arr_twodim[3][4] = {{-641, -642, -643, -644}}; 
enum DAY {MON=1,TUE,WED,THU,FRI,SAT,SUN}; 
// user defined type global variable 
__gm__ enum DAY day = FRI; 
struct SIMPLE{int32_t i32;uint8_t ui8;int16_t i16;}; 
struct COMPLEX{bool b;struct SIMPLE simple;}; 
__gm__ struct COMPLEX complex = {true, {-32, 8, -16 }}; 
union DATA{int32_t u_i32;uint64_t u_ui64;uint8_t  arr_ui8[16];}; 
__gm__ union DATA data = {.u_i32 = 32}; 
// pointers 
__gm__ int* __gm__ p;               // declares a pointer p in the gm address space  
                                    //that points to an object in the gm address space 
int * __gm__ p2;                    // declares a pointer p2 in the gm address space  
                                    //that points to an object in the private address space, 
                                    //usually on the stack 
// reference global variable 
__global__ [aicore] void kernel(__gm__ int* hbm_out) { 
  *hbm_out++ = int32_t_arr_a[1]; 
  *hbm_out++ = complex.simple.i32; 
}

由于异构程序中Device侧代码和runtime配合模式的特殊性,Device侧全局变量的使用需参见注意事项

注意事项

  • 在Host侧,main函数前会有一些初始化代码运行,用于调用如全局的类的构造等。然而,对于异构程序的代码运行,并没有初始化阶段,runtime在Device直接加载并运行kernel,所以Device侧全局变量只支持POD(Plain Old Data,没有构造函数)类型的全局变量。
    struct A { int m; }; 
    __gm__ struct A a={1};                 //OK 
    class B: public A { int m; }; 
    __gm__ struct B b;                    //Error, B is not a POD class 
    struct C { virtual void foo(); }; 
    __gm__ struct C c;                    //Error, C is not a POD class
  • 在通用CPU上,未初始化的全局变量通常是没有大小的,系统在加载的时候给它们分配的空间,当前昇腾AI处理器不支持加载.bss段,因此未初始化的全局变量也会一并放在.data段。此约束会导致编译出来的二进制较大。
  • 只读的全局变量(常量)在.rodata段。
  • 当前芯片的实现当数据从Cacheline逐出时,是整条Cacheline一起反刷到DDR,为了防止反刷时弄脏DDR上的数据,全局变量必须是Cacheline长度对齐。芯片Cacheline是256Byte。
  • 开发者需要注意,多个block之间写同一个全局变量,最后的结果是跟调度相关的。