我通过尝试优化mpeg4dst参考音频编码器来自学OpenCL。我通过在CPU上使用向量指令实现了3倍的加速,但我认为GPU可能做得更好。
我专注于计算OpenCL中的自相关向量作为我的第一个改进领域。 CPU代码是:
for (int i = 0; i < NrOfChannels; i++) {
for (int shift = 0; shift <= PredOrder[ChannelFilter[i]]; shift++)
vDSP_dotpr(Signal[i] + shift, 1, Signal[i], 1, &out, NrOfChannelBits - shift);
}
NrOfChannels = 6
PredOrder = 129
NrOfChannelBits = 150528.
在我的测试文件中,此功能大约需要188毫秒才能完成。
这是我的OpenCL方法:
kernel void calculateAutocorrelation(size_t offset,
global const float *input,
global float *output,
size_t size) {
size_t index = get_global_id(0);
size_t end = size - index;
float sum = 0.0;
for (size_t i = 0; i < end; i++)
sum += input[i + offset] * input[i + offset + index];
output[index] = sum;
}
这就是它的名称:
gcl_memcpy(gpu_signal_in, Signal, sizeof(float) * NrOfChannels * MAXCHBITS);
for (int i = 0; i < NrOfChannels; i++) {
size_t sz = PredOrder[ChannelFilter[i]] + 1;
cl_ndrange range = { 1, { 0, 0, 0 }, { sz, 0, 0}, { 0, 0, 0 } };
calculateAutocorrelation_kernel(&range, i * MAXCHBITS, (cl_float *)gpu_signal_in, (cl_float *)gpu_out, NrOfChannelBits);
gcl_memcpy(out, gpu_out, sizeof(float) * sz);
}
根据Instruments的说法,我的OpenCL实现似乎需要大约13ms,大约54ms的内存拷贝开销(gcl_memcpy)。
当我使用更大的测试文件时,1分钟2声道音乐与1声道6声道,而OpenCL代码的测量性能似乎相同,CPU使用率降至约50%并且整个程序运行时间要长2倍。
我无法在仪器中找到原因,但我还没有读过任何表明我应该期望在OpenCL中进出非常繁重的开销。
答案 0 :(得分:2)
如果我正确地读取内核代码,每个工作项都会迭代从其位置到结尾的所有数据。这不会有效。对于一个(以及主要性能问题),内存访问将不会合并,因此不会处于完全内存带宽。其次,因为每个工作项的工作量不同,工作组内会出现分支差异,这会使一些线程空闲等待其他工作。
这似乎与减少问题有很多共同点,我建议阅读“并行减少”以获得有关并行执行此类操作的一些提示。
要了解如何读取内存,请确定16个工作项(例如,global_id 0到15)将如何读取每个步骤的数据。
请注意,如果工作组中的每个工作项都访问相同的内存,则硬件可以进行“广播”优化。因此,只需颠倒循环的顺序就可以改善事情。