我目前正在实现一种在小矩阵和向量上分配线性代数的算法。代码很快,但我想知道在gpgpu而不是cpu上实现它是否有意义。
我能够将大多数矩阵和向量存储在gpu内存中作为预处理步骤,并且具有乘法算法的配置文件,这些算法在gpu上更快。
但现在我的真实问题, 如何确定从cpu调用gpu的开销?我失去了多少个循环以便我的代码被执行以及类似的东西?
我希望有人有一些意见吗?
答案 0 :(得分:6)
很难确定调用OpenCL的确切“开销”,因为GPU上的操作可以与CPU上运行的任何其他操作并行完成。 例如,根据您的应用程序,您可以从应用程序中将一大块数据传输到GPU,并且在以下数据块的CPU中进行一些预处理。类似地,当代码在GPU上执行时,您可以在CPU上对将来需要的某些数据进行一些准备工作。
转移到GPU将通过DMA传输完成,这种传输速度非常快。 根据我的经验,我能够以4毫秒的顺序将大约4MB的数据传输到GPU(现代GPU,现代主板),同时对先前发送的数据进行一些处理。 由此可以肯定地说,您可以每秒向GPU上传和下载1GB数据的订单,并对该数据进行一些处理。
在您的情况下,GPU或CPU端将成为瓶颈。 CPU端,如果它不能每秒向GPU提供1GB的准备数据。这可能很可能受到磁盘I / O的限制。
要测试GPU路径,请设置一堆准备处理的数据缓冲区。您可能希望继续将该数据重新发送到GPU,处理它并下载结果(您将丢弃)。测量吞吐量并与应用程序的CPU版本的吞吐量进行比较。
不要只测量GPU处理部分,因为GPU上的传输和处理将争夺GPU内存控制器的时间并且会影响彼此的速度。
此外,如果您希望在小块数据上获得非常好的响应时间,而不是良好的吞吐量,则可能无法通过GPU获益,因为它会给您的处理带来一些延迟。
答案 1 :(得分:2)
这里需要考虑的重要事项是将数据复制到GPU并返回所需的时间。即使GPU实现速度更快,执行传输所花费的时间也可能消除任何优势。
此外,如果您非常认真考虑代数的准确性,那么您可能需要考虑您想要执行的操作可能无法在GPU上以原生方式提供,并具有双倍的准确性。
鉴于您说您的矩阵和向量很小,我建议您检查SIMD优化,这可能会提高您的算法在CPU上的性能。
答案 2 :(得分:1)
您可以使用clEvent对象来跟踪实际计算所花费的时间(延迟)。如果您实际上是指CPU周期,请使用RDTSC(或其内在函数,MSVC中的__rdtsc)为实际的API调用执行纳秒级精确计时。 RDTSC指令(读时间戳计数器)返回自上电以来cpu完成的时钟周期数。
如果真的很容易上传,那么您可以批量调用并可能为NDRange添加维度以在一次调用中进行多次计算。当然,细节取决于您的内核实现。
答案 3 :(得分:-1)
我建议使用以下方法来测量cpu周期数:
#include <stdlib.h>
#include <time.h>
// ...
clock_t start,end;
start = clock();
// do stuff...
end = clock();
cout<<"CPU cycles used: "<<end-start;