估计OpenCL寄存器的使用

估计OpenCL寄存器的使用,opencl,Opencl,当编译器查看内核并分配寄存器时,是否有一条经验法则可以让它满意 编译器有很大的灵活性,但我担心如果我在内核中创建500个变量,它可能会开始使用过多的本地内存。。。或者是一条很长的单条生产线,有大量的业务 我知道我的程序能够真正检查登记在特定设备上的唯一方法是使用AMD SDK或英伟达SDK(或者将汇编代码与设备的体系结构进行比较)。不幸的是,我使用的是PyOpenCL,因此使用这些SDK是不切实际的 我的程序生成半随机内核,我试图阻止它做一些会阻塞编译器并开始在本地内存中转储寄存器的事情。编译器

当编译器查看内核并分配寄存器时,是否有一条经验法则可以让它满意

编译器有很大的灵活性,但我担心如果我在内核中创建500个变量,它可能会开始使用过多的本地内存。。。或者是一条很长的单条生产线,有大量的业务

我知道我的程序能够真正检查登记在特定设备上的唯一方法是使用AMD SDK或英伟达SDK(或者将汇编代码与设备的体系结构进行比较)。不幸的是,我使用的是PyOpenCL,因此使用这些SDK是不切实际的


我的程序生成半随机内核,我试图阻止它做一些会阻塞编译器并开始在本地内存中转储寄存器的事情。

编译器将跟踪私有变量的作用域,重要的不是你声明的变量数量,而是如何使用它们

例如,在下面的示例中,仅使用2个寄存器。虽然使用了5个专用变量:

//Notice here, that a value is used in the register when it has to be stored
// not when it is declared. So declaring a variable that is never used will be
// optimized and removed by the compiler.

R1 | R2 |  Code
 a |  - |  int a = 1;
 a |  b |  int b = 3;
 a |  b |  int c;
 c |  b |  c = a + b;
 c |  b |  int d;
 c |  d |  d = c + b;
 c |  d |  int e;
 e |  - |  int e = c + d;
 - |  - |  out[idx] = e; //Global memory output
这完全取决于变量的范围(何时需要,是否需要,以及需要多长时间)


唯一关键的事情是,如果编译器无法预测内存,那么不要创建超过需要的内存

 int a[100];
 //Initialize a with some value
 int b;
 b = a[global_index];

编译器将无法预测您正在使用的值,因此它需要100个值,并将在需要时释放内存。对于这类操作,最好创建一个表,甚至对一个全局表进行一次读取。

编译器将跟踪私有变量的作用域,重要的不是您声明的变量数量,而是它们的使用方式

例如,在下面的示例中,仅使用2个寄存器。虽然使用了5个专用变量:

//Notice here, that a value is used in the register when it has to be stored
// not when it is declared. So declaring a variable that is never used will be
// optimized and removed by the compiler.

R1 | R2 |  Code
 a |  - |  int a = 1;
 a |  b |  int b = 3;
 a |  b |  int c;
 c |  b |  c = a + b;
 c |  b |  int d;
 c |  d |  d = c + b;
 c |  d |  int e;
 e |  - |  int e = c + d;
 - |  - |  out[idx] = e; //Global memory output
这完全取决于变量的范围(何时需要,是否需要,以及需要多长时间)


唯一关键的事情是,如果编译器无法预测内存,那么不要创建超过需要的内存

 int a[100];
 //Initialize a with some value
 int b;
 b = a[global_index];

编译器将无法预测您正在使用的值,因此它需要100个值,并将在需要时释放内存。对于这些类型的操作,最好创建一个表,甚至对一个全局表执行一次读取。

NVIDIA平台有一个选项,它甚至可以在没有SDK的情况下以编程方式工作。(也许AMD卡也有类似的功能?)

调用
clBuildProgram
时,可以将
“-cl nv verbose”
指定为“构建选项”。这将生成一些日志信息,稍后可以通过构建日志获得这些信息

clBuildProgram(program, 0, NULL, "-cl-nv-verbose", NULL, NULL);
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, ...);
(对不起,我不确定这个的python语法)

结果应该是包含所需信息的字符串。对于简单的向量加法,如下所示

ptxas : info : 0 bytes gmem
ptxas : info : Compiling entry function 'sampleKernel' for 'sm_21'
ptxas : info : Function properties for sampleKernel
    0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas : info : Used 4 registers, 44 bytes cmem[0], 4 bytes cmem[16]

您也可以使用
“-cl nv maxrregcount=…”
选项来指定最大寄存器计数,但当然,所有这些都是特定于设备和平台的,因此应小心使用。

对于NVIDIA平台,甚至可以在没有SDK的情况下以编程方式工作。(也许AMD卡也有类似的功能?)

调用
clBuildProgram
时,可以将
“-cl nv verbose”
指定为“构建选项”。这将生成一些日志信息,稍后可以通过构建日志获得这些信息

clBuildProgram(program, 0, NULL, "-cl-nv-verbose", NULL, NULL);
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, ...);
(对不起,我不确定这个的python语法)

结果应该是包含所需信息的字符串。对于简单的向量加法,如下所示

ptxas : info : 0 bytes gmem
ptxas : info : Compiling entry function 'sampleKernel' for 'sm_21'
ptxas : info : Function properties for sampleKernel
    0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas : info : Used 4 registers, 44 bytes cmem[0], 4 bytes cmem[16]
您还可以使用
“-cl nv maxrregcount=…”
选项指定最大寄存器计数,但当然,所有这些都是特定于设备和平台的,因此应小心使用