AMD OpenCL 降低寄存器压力

问题描述 投票:0回答:3

我在内核中运行排序算法,排序部分使用了大约 36 VGPR,从而导致 12.5% 的占用率和糟糕的性能。

代码段如下:

typedef struct {
  float record[8];
  float dis;
  int t_class;
} node;


for ( int i = 0 ; i < num_record ; i ++ ){
  in_data [ i]. dis = Dist ( in_data [i]. record , new_point , num_feature );
}


node tmp ;
int i;
int j;
#pragma unroll 1
for ( i = 0 ; i < num_record - 1 ; i ++ )
  for ( j = 0 ; j < num_record - i - 1 ; j ++ )
  {
    if ( in_data [ j]. dis > in_data [ (j + 1) ]. dis )
    {
      tmp = in_data [ j ];
      in_data [ j ] = in_data [ (j + 1) ];
      in_data [ (j + 1) ] = tmp ;
    }
  }

有没有什么方法可以减少寄存器的使用而不需要对算法本身进行大的修改?我想把寄存器减少到16以下会更好。

更新:

基本上内核正在尝试实现详尽的 knn 方法。

optimization opencl cpu-registers amd-gpu
3个回答
0
投票
float tmp;

tmp = in_data [ j ].x;
in_data [ j ].x = in_data [ (j + 1) ].x;
in_data [ (j + 1) ].x = tmp ;

tmp = in_data [ j ].y;
in_data [ j ].y = in_data [ (j + 1) ].y;
in_data [ (j + 1) ].y = tmp ;

tmp = in_data [ j ].z;
in_data [ j ].z = in_data [ (j + 1) ].z;
in_data [ (j + 1) ].z = tmp ;

应该使用原始代码的 1/3 寄存器,因为它一次只需要 1/3 空间。

你也可以做一个全局--->本地------>全局

代替 global -----> private -----> global 来减少私有寄存器的使用。


0
投票

现在我记得了,AMD 因在使用循环展开时使用大量寄存器而闻名。如果您的

num_record
是编译器已知的固定值,它可能会进行一些展开,并创建
tmp
的副本。

您可以尝试设置 pragma unroll 或在循环内声明

tmp
参数吗?

可能性1:

node tmp;
#pragma unroll
for ( int i = 0 ; i < num_record - 1 ; i ++ )
 #pragma unroll
 for ( int j = 0 ; j < num_record - i - 1 ; j ++ )
 {
  if ( in_data [ j]. dis > in_data [ (j + 1) ]. dis )
  {
   tmp = in_data [ j ];
   in_data [ j ] = in_data [ (j + 1) ];
   in_data [ (j + 1) ] = tmp ;
  }
}

可能性2:

for ( int i = 0 ; i < num_record - 1 ; i ++ )
 for ( int j = 0 ; j < num_record - i - 1 ; j ++ )
 {
  if ( in_data [ j]. dis > in_data [ (j + 1) ]. dis )
  {
   node tmp = in_data [ j ];
   in_data [ j ] = in_data [ (j + 1) ];
   in_data [ (j + 1) ] = tmp ;
  }
}

0
投票

根据你的描述,你的

node
结构看起来或多或少像这样(我假设
dis
是一个
int
,但无论是真的
int
还是
float
并不重要):

struct node
{
    int dis;
    float f1;
    ...
    float f9;
};

如果简单的更改没有帮助...如何在

index
中再添加一个字段
node
,这样可以唯一地标识节点(除非可以使用现有字段之一来完成)并引入
 node2
结构仅包含
index
dis
? 像这样的东西:

struct node
{
    int index; // add index for uniqueness unless one of f1 ... f1 could do
    int dis;
    float f1;
    ...
    float f9;
};

struct node2
{
    int index; // add index for uniqueness unless one of f1 ... f1 could do
    int dis;
};

然后使用

node2
进行排序,然后在另一个内核或主机上使用已排序的
node
index
进行排序
node2

这应该会减少排序内核中的寄存器压力,但需要更多更改,例如已经说过的引入新的

node2
以及可能的内核分裂。

© www.soinside.com 2019 - 2024. All rights reserved.