OpenCL结果会根据printf的结果而变化吗?什么?

时间:2015-07-14 16:13:17

标签: vector opencl

OpenCL内核压缩了一些数字。然后,该特定内核在8位char4向量的数组中搜索匹配的数字串。例如,数组保持3 67 8 2 56 1 3 7 8 2 0 2 - 内核循环(实际字符串长度为1024位)并搜索1 3 7 8 2和"返回"让主机程序知道它找到匹配的数据。

在组合学习练习/编程实验中,我想看看是否可以遍历数组并搜索一系列值,其中数组不仅仅是char值,而是char4向量,没有使用单个if语句内核。有两个原因:

1:在收到编译错误半小时后,我意识到你不能这样做:

if(charvector[3] == searchvector[0])

因为有些可能匹配,有些可能不匹配。 2:

我是OpenCL的新手,我已经阅读了很多关于分支如何损害内核速度的内容,如果我理解内核的内部结构,一些数学实际上可能比如果声明。是这样的吗?

无论如何......首先,有问题的内核:

void search(__global uchar4 *rollsrc, __global uchar *srch, char srchlen)
{
  size_t gx = get_global_id(0);
  size_t wx = get_local_id(0);
  __private uint base = 0;
  __local uchar4 queue[8092];
  __private uint chunk = 8092 / get_local_size(0);
  __private uint ctr, start, overlap = srchlen-1;
  __private int4 srchpos = 0, srchtest = 0;
  uchar4 searchfor;
  event_t e;

  start = max((int)((get_group_id(0)*32768) - overlap), 0);

  barrier(CLK_LOCAL_MEM_FENCE);
  e = async_work_group_copy(queue, rollsrc+start, 8092, 0);
  wait_group_events(1, &e);

  for(ctr = 0; ctr < chunk+overlap; ctr++) {
    base = min((uint)((get_group_id(0) * chunk) + ctr), (uint)((N*32768)-1));
    searchfor.x = srch[max(srchpos.x, 0)]; 
    searchfor.y = srch[max(srchpos.y, 0)]; 
    searchfor.z = srch[max(srchpos.z, 0)]; 
    searchfor.w = srch[max(srchpos.w, 0)]; 
    srchpos += max((convert_int4(abs_diff(queue[base], searchfor))*-100), -100) | 1;
    srchpos = max(srchpos, 0);
    srchtest = clamp(srchpos-(srchlen-1), 0, 1) << 31;
    srch[0] |= (any(srchtest) * 255); 

//  if(get_group_id(0) == 0 && get_local_id(0) == 0) 
//    printf("%u: %v4u   %v4u\n", ctr, srchpos, srchtest);
  }
  barrier(CLK_LOCAL_MEM_FENCE);
}

那里有额外不需要的代码,这是以前内核的副本,我还没有清理掉额外的垃圾。这就是说...简而言之,英语,基于if语句的数学如何运作:

由于我需要搜索范围,并且我正在搜索矢量,所以我首先设置一个char4矢量(searchfor),将元素xyzw分别设置为我要搜索的数字。它是单独完成的,因为xyz和w中的每一个都拥有不同的流,并且搜索计数器 - 我们已经连续多少匹配 - 对于每个向量成员将是不同的。我确信这比我做的更好。建议?

那么,一个int4向量,searchpos,它保存搜索数组中4个向量位置中每个位置的当前位置,并将其添加到其中:

max((convert_int4(abs_diff(queue[base], searchfor))*-100), -100) | 1;

这样做:获取目标队列(队列)中当前位置与前4行中搜索向量的ABS差异。返回一个向量,其中每个成员将具有正数(不匹配)或零(匹配 - 无差异)。

它转换为int4(因为uchar不能为负)然后乘以-100,然后运行max(x,-100)。现在向量是-100或0.我们或者它是1,现在它是-99或1.

结束结果:searchpos要么递增1(匹配),要么减少99,重置之前的任何部分匹配增量。 (搜索最长可达96个字符 - 有机会匹配91,然后错过,所以它必须能够全部擦除)。然后最大值为0,因此任何负面结果都被钳制为零。再次 - 接受建议,以提高效率。我意识到,当我写这篇文章时,我可能会使用饱和度来删除一些最大语句。

最后一部分采用当前的srchpos,现在等于连续匹配的数量,减去1比搜索字符串的长度小,然后将其钳制到0-1,从而最终得到1 - 完全匹配或者0.我们将这个&lt;&lt;&lt;&lt; 31.结果为0或0x8000000。把它放到srchtest。

最后,我们将搜索字符串的第一个字符与任意(srchtest)* 255的结果进行按位OR运算 - 它是少数几种方式之一(我知道)在向量并从中返回一个整数。 (如果向量的任何成员具有它的MSB集,则any()返回1 - 我们在上面的行中设置)

最终结果? srch [0]未更改,或者在匹配的情况下,它设置为0xff。当内核返回时,主机可以从缓冲区读回srch。如果第一个字符是0xff,我们找到了匹配。

它可能有太多步骤,可以清理。如果每个循环检查,它也可能效率低于仅执行4。不确定。

但是,在这篇庞大的帖子之后,让我脱掉头发的东西:

当我在最后输出打印调试信息的两行时,脚本可以工作。当我运行它时,这是终端窗口输出的结束:

36: 0,0,0,0   0,0,0,0
37: 0,0,0,0   0,0,0,0
38: 0,0,0,0   0,0,0,0
39: 0,0,0,0   0,0,0,0

Search = 613.384 ms
Positive
Done read loop: -1 27 41

正面意味着找到了字符串。 -1 27 41是搜索字符串的前3个字符,第一个设置为-1(主机端的signed char)。

这是我在注释掉printf调试信息时会发生什么:

Search = 0.150 ms
Negative
Done read loop: 55 27 41

它没有找到它。什么?!怎么可能?当然,我注意到由于printf,脚本执行时间从.15ms跳到600 + ms,所以我想,也许它会以某种方式返回并在脚本结束之前读取数据,以及来自printf给它一个暂停。所以我添加了一个屏障(CLK_LOCAL_MEM_FENCE);到最后,认为这将确保所有线程在返回之前完成。不。没有效果。然后在运行内核之后,在运行clFinish之后,在运行clReadBuffer之前,在主机端添加2秒的睡眠。

NOPE!仍然是负面的。但我把printf放回去了 - 它有效。怎么可能?为什么?有谁有想法吗?这是我第一次遇到编程错误让我感到困惑,因为它完全没有意义。工作项没有冲突,它们每个都读取自己的块,甚至在搜索字符串被分成两个工作项块时重叠。

请 - 保存我的头发 - 无关数据的printf怎么能导致这种情况发生并且删除它会导致它没有?

哦 - 最后一件有趣的事情:如果我从printf中删除参数 - 只需打印文本就像&#34; grr请工作&#34; - 内核返回负数,AND,没有打印出来。 printf被忽略。

到底发生了什么事?感谢阅读,我知道这太荒谬了。

0 个答案:

没有答案