我正在编写一个openCL内核来为益智游戏执行基于暴力的AI,但是我的内核代码和/或它调用的辅助函数存在问题。这是我的内核代码(我确信输入正确传递到这里):60是clEnqueueNDRangeKernel设置的全局工作大小。
内核的输入如下:
__ global char * in //虚拟输入用于测试目的
__ global char * board_in,//包含60个板的大型字符数组
__ global int * lookup,//我用来快速获得得分移动分数的数组
输出:
__ global char * out,//用于测试的虚拟输出
__ global int * score_out,//一个包含60个分数的数组:每个棋盘一个
__ global int * row_out,//一个包含60行的数组:每个评估的一个板
__ global int * col_out // 60列的数组:...
__kernel void helloworld(__global char* in,
__global char* board_in,
__global int* lookup,
__global char* out,
__global int * score_out,
__global int * row_out,
__global int * col_out)
{
int num = get_global_id(0);
char workingBoard[72];
int scoreMat[64];
//set up the array for each thread to use
for(int k=0; k< 72; k++)
{
workingBoard[k] = board_in[num*BOARDSIZE+k];
}
// Make a copy of the score matrix for each thread to use
for(int j=0; j<64; j++)
{
scoreMat[j] = lookup[j];
}
int s=0;
int r=0;
int c=0;
findBestMove(workingBoard,scoreMat,&s,1,&r,&c);
col_out[num] = ?????????
score_out[num] = ???????????
row_out[num] = ???????????????
}
函数findBestMove的工作原理如下(经过充分测试。我已经在CPU实现中使用了一段时间): 它需要一个Board(字符数组),一个分数查找数组,一个指向移动得分的指针,当前深度以及指向行和列的指针。它应该设置分数,行和列。它调用我在同一文档中定义的其他函数。
如果我在CPU上运行此代码片段,我会得到正确的输出:
// workerBoard and lookuparr are set previous to this to be the same as what
//the kernel thread is supposed to have
int s=0;
int r=0;
int c=0;
findBestMove(workerBoard,lookuparr,&s,1,&r,&c);
cout<<s<<","<<r<<","<<c<<endl;
当我运行我的内核代码时,我没有通过函数调用。该函数在与内核相同的文档中定义,不使用动态内存,函数指针,递归或全局内存(在内核args之外)。我确实使用了一些#define语句。
我想设置????我的内核的部分是r,c和s,但如上所述,我没有到达那里。我是否犯了任何重大错误(注意:内核通过了我的代码检查程序和AMD的内核分析器)。另外,我对openCL很新,所以任何提示都是受欢迎的。如果我能提供更多信息来帮助回答这个问题,请告诉我们!
答案 0 :(得分:0)
根据您的评论似乎问题出现在findBestMove函数中。顺便说一句,如果你有一个无限循环,看门狗会在一个点触发,很可能你的驱动程序会因黑屏或冻结而崩溃。
所以我建议您在函数中注释所有代码,并为r,s,c变量分配一个选定的值,例如使用get_global_id函数处理这些特定变量的工作项id。当然要更换???用:
col_out[num] = c;
score_out[num] = s;
row_out[num] = r;
如果你得到了正确的值,就可以开始调试你的功能,你肯定知道你的问题在于函数。
因为你在这里要求提供一些技巧,我认为这会提高性能(一旦你修复了你的错误:)):而不是使用你的scoreMat数组的私有内存使用本地内存。这样做可以避免让每个线程一遍又一遍地访问全局内存中的相同数据(这很慢)。要从全局内存中获取数据到本地内存,可以使用async_work_group_copy函数。
所以在你的情况下,你会有这样的事情:
local int scoreMat[64];
event_t ev = async_work_group_copy(lookup, scoreMat, 64, 0);
// Wait to make sure everything is copied
wait_group_events (1, &ev);
您可能需要更改一些代码以考虑您现在使用本地内存。基本上它的工作方式与全局工作方式相同(从接入的角度来看),但速度要快得多。
请注意,与您所拥有的不同之处在于,只有一个副本不是60(工作项数)。此时,您从全局获取的数据也可以从工作组中的所有工作项访问。在每个工作项拥有它自己的副本之前。强调在工作组中这一事实也很重要。但由于您只使用了60个工作项,因此您最有可能只有一个工作组。