我正在尝试第一次使用opencl,目标是计算数组中每一行的argmin。由于每一行的操作都独立于其他行,因此我认为将其轻松放在图形卡上是很容易的。
与仅使用外部forloop在cpu上运行代码时相比,使用此代码似乎可以获得更差的性能。
这是代码:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
int argmin(global double *array, int end)
{
double minimum = array[0];
int index;
for (int j = 0; j < end; j++)
{
if (array[j] < minimum)
{
minimum = array[j];
index = j;
}
}
return index;
}
kernel void execute(global double *dist, global long *res, global double *min_dist)
{
int row_size = 0;
int i = get_global_id(0);
int row_index = i * row_size;
res[i] = argmin(&dist[row_index], row_size);
min_dist[i] = dist[res[i] + row_index];
}
答案 0 :(得分:0)
评论者提出了一些有效的观点,但我会尝试使其更具建设性和组织性:
double
个精度浮点值组成。根据您的GPU,这本身可能是个坏消息。消费级GPU通常并未针对使用double
进行优化,与单精度float
操作相比,通常仅达到1/32或1/16的吞吐量。不过,许多专业级GPU(Quadro,Tesla,FirePro和某些Radeon Pro卡)都可以使用,与float
相比,可实现1/2或1/4的吞吐量。由于您仅执行简单的算术运算(比较),并且很有可能您的运行时由内存访问控制,因此在消费类硬件上也可以。row_size
实际上不是0,这将有助于知道真实(典型)值是什么,以及它是固定的,逐行还是每次运行都可变,但每一行都相同。无论如何,除非row_size
非常小,否则您正在其上运行串行for
的事实可能会使您的代码受阻。改进建议:
row_size
非常小(并且固定),否则请尝试将循环拆分为多个工作项,并使用局部内存(归约算法)和全局内存中的原子操作进行协调。double
太慢,请检查是否可以将数据生成为float
而不损失准确性(这也将使您的内存带宽问题减少一半),或者检查是否可以通过其他方式做得更好,例如,将double
视为long
,并手动拆包并比较指数和尾数使用整数运算。