二进制搜索是否适合OpenCL
Is a binary search a good fit for OpenCL?
我正在编写一个OpenCL程序,该程序需要根据白名单检查计算的(int
)值。我的计划是将白名单存储在常量或共享内存中,然后让每个线程使用这个共享白名单运行二进制搜索。
然后我读到像银行冲突这样的事情,线程因为访问同一银行上的内存而变慢,这会导致访问的序列化发生。
由于这样的问题,二进制搜索会导致OpenCL上更大的性能损失吗?用其他的搜索算法会更好吗,比如散列?
编辑让我稍微澄清一下我的程序:
每个线程将执行并行计算,但使用不同的输入值。因此,每个线程将获得不同的输出。每个输出都需要根据相同的白名单进行检查。
内核将返回一个bool值,该值表示搜索结果。
我担心的是,由于每个线程都在进行独立的二进制搜索,因此多个线程最终将访问白名单的同一组,从而导致连续减速。
如果您在每个线程中搜索不同的项,那么与其担心银行冲突,还不如担心线程分歧,因为二进制搜索需要分支。其中一些可以使用select
函数来缓解。
你可以更好地使用其他算法,比如插值搜索,它可以在更少的跳数中找到项目(本质上,决定下一步在哪里查找比二进制搜索更昂贵,但如果你的搜索数据在全局内存中,你可以隐藏很多处理(大约20条指令)在内存延迟下)。
我最近正在解决一个类似的问题:带提示的二进制搜索。
一个简化的算法是这样的:
__global const _TyIndex *upper_bound(__global const _TyIndex *begin,
__global const _TyIndex *end, const _TyIndex elem)
{
while(begin != end) {
__global const _TyIndex *mid = begin + (end - begin) / 2;
#if 0
if(!(elem < *mid))
begin = mid + 1; // look to the right
else
end = mid; // look to the left
#else // 0
bool b_right = !(elem < *mid);
begin = (__global const _TyIndex *)select((intptr_t)begin, (intptr_t)(mid + 1), b_right);
end = (__global const _TyIndex *)select((intptr_t)mid, (intptr_t)end, b_right); // c ? b : a
#endif // 0
}
return begin;
}
这是两次使用select()
而不是分支。您可以通过将#if 0
更改为#if 1
来比较性能。请注意,e? a : b
确实暗示了一个分支,所以使用它没有帮助。
如果预先计算的int类型列表没有改变(只读数据),并且线程没有修改它,那么使用不同步的二进制搜索是完全可以的。线程可能因为同步问题而变慢。哈希有时比二分查找更快,但它对更大的数组更有用。先用二进制搜索。
你也可以看到:同时从多个线程访问只读数据是明智的吗?
听起来您在每个内核中进行二进制搜索是作为其他工作的一部分。最好先找到搜索的结果,然后将结果作为参数传递给内核。
一般来说,二分查找是一个logn算法,应该不会很慢,除非你在一个非常非常大的列表中查找值。但是,如果在每个内核中进行相同的搜索,仍然是对资源的浪费。如果你想并行化搜索本身,它仍然是低效的,因为在算法的每一级/迭代中,你只有2个核来执行核。在此基础上添加任何其他主程序-> opencl开销。最好使用线性搜索,将白名单分割成尽可能多的核。与二进制搜索相比,在列表的单个部分查找值可能需要更长的时间,但在主程序和内核之间传递值的开销更少。
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 使用std::vector的OpenCL矩阵乘法
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 此代码是否违反一个定义规则
- OpenCL 是否支持向量作为内核参数?
- 是否可以在多线程而不是 cuda/opencl C++运行 GPU?
- OPENCL,是否可以直接写入本地内存
- 各种 OpenCL 样板类型是否可以安全复制
- 是否有OpenCL 2.2功能,可在OpenCL C 中使用,但在OpenclC中不可用
- 是否可以在同一设备缓冲区上一个接一个地调用 OpenCL 内核?
- 这是否应该给出错误,如果是,如何检查它?(OpenCL)
- C/C++应用程序是否可以使用 OpenCL
- 二进制搜索是否适合OpenCL
- 是否有可能在OpenCL中并行运行求和计算?
- 是否可以用 C++ 而不是 C 编写 OpenCL 内核
- Radeon卡是否可以从DisplayPort(使用OpenCL)读取数据?