OpenCL代码如下:
typedef struct {
float record[8];
float dis;
int t_class;
}node;
float Dist ( __global float * a , __global float * b , int width ) {
float rst = 0;
for (int i =0; i < width; i++){
rst += (a[i] - b[i])*(a[i] - b[i]);
}
return sqrt(rst);
}
__kernel void ex_knn ( __global node * in_data , __global node * in_data_copy, int num_record , int num_feature, __global float * new_point , int k , __global node * rst )
{
int idx = get_global_id(0);
for(int i=0;i<4177;i++){
in_data_copy[idx*4177 + i] = in_data[i];
}
for (int i=0; i < num_record; i++){
in_data_copy [idx*4177 + i ]. dis = Dist ( in_data_copy [idx*4177 + i ]. record , new_point , num_feature );
}
node tmp;
for (int i=0; i< num_record-1;i++)
for (int j =0; j<num_record-i-1; j++)
{
if ( in_data_copy [ idx*4177 + j ]. dis > in_data_copy [idx*4177 + j + 1 ]. dis )
{
tmp = in_data_copy [ idx*4177 + j ];
in_data_copy [ idx*4177 + j ] = in_data_copy [ idx*4177 + j + 1 ];
in_data_copy [ idx*4177 + j + 1 ] = tmp ;
}
}
for (int i=0;i<k;i++)
rst [ idx * k + i ] = in_data_copy [ idx*4177 + i ];
}
我发现此代码段错误,但我不知道为什么。 基本上,它是一种在多个线程上运行数据集副本的knn方法。 in_data_copy是多个数据集副本的全局内存部分。这意味着,每个单个线程都有一个数据集副本。 然后我做了详尽的knn方法,计算距离和排序。
我知道这里可能存在竞争条件,一些线程可能会计算距离,而其他一些线程可能会进行交换。然而,这些线程正在处理'in_data_copy'的不同块,这有关系吗?
当我运行程序时,交换前的所有代码都正确运行。 进入交换时,OpenCL代码停在某处并退出程序。知道为什么会这样吗?
答案 0 :(得分:1)
假设你没有超出Dist()
和in_data_copy
范围内的界限,结构对齐很可能就是问题所在。您需要将结构与2尺寸的下一个幂对齐。目前您的结构大小为40字节,下一次2的幂为64字节。您可以通过在顶部添加6个4字节元素数组或在底部添加6个4字节成员来填充结构。第二个选项可能如下所示:
typedef struct {
float record[8];
float dis;
int t_class;
int pad1;
int pad2;
int pad3;
int pad4;
int pad5;
int pad6;
}node;
注意:重要的是要将结构从最宽的类型首先声明为最窄的,以避免使用未使用的空间和不同设备上的不同对齐方式的潜在问题。