OpenCV GPU库在矩阵运算方面有多好?

问题描述 投票:7回答:2

我正在将OpenCV用于计算机视觉中的应用程序。我想在GPU上加速某些矩阵运算(矩阵相当大),并希望避免在可能的情况下直接在CUDA C中进行编码。 OpenCV 2.4.1具有许多GPU加速功能。他们在您的体验中表现如何?我最好改用另一个库(例如Thrust)吗?

编辑示例应用程序:Calculate squared Euclidean distance matrix on GPU。目前,我在Matlab中使用并行计算工具箱(PCT)进行GPU加速(和矢量化)的实现比我使用OpenCV的C ++实现快约5-10倍。

Matlab实现:

function K = sqEuclideanDist(P_cpu,Q_cpu)
% Vectorized method to compute pairwise squared Euclidean distance on GPU
% Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:))

P_gpu = gpuArray(P_cpu);
Q_gpu = gpuArray(Q_cpu);

[nP, d] = size(P_gpu);
[nQ, d] = size(Q_gpu);

pmag = sum(P_gpu .* P_gpu, 2);
qmag = sum(Q_gpu .* Q_gpu, 2);

% note that K is on GPU
K = ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P_gpu*Q_gpu';

end

UPDATE这是另一个实现相同功能的Matlab实现(由于[C​​0])。但是它仅在CPU上运行,因为PCT不支持https://stackoverflow.com/a/7774323/1121420。仍在寻找C ++替代方案。

bsxfun
c++ opencv cuda gpu thrust
2个回答
4
投票

我发现function K = sqEuclideanDist(P_cpu,Q_cpu) % Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:)) % Runs on CPU only. K = bsxfun(@plus,sum(p.^2,2),sum(q.^2,2)') - 2*(p*q'); end 更快,并且已经开始使用它来代替OpenCV中的GPU内核进行图像处理。这是ArrayFire,我发现将ArrayFire(以前在另一个名为LibJacket的接口中)与OpenCV进行了比较,在我的基准测试中也是如此,ArrayFire比OpenCV中的GPU功能快2-4倍。据我了解,NVIDIA没有在OpenCV中编写GPU内核,而是将这些内核外包给了某人,这可能就是为什么它们这么慢的原因。由于我只使用1个GPU,因此可以免费使用ArrayFire。

更新,给定@Alex发布的新MATLAB代码:我在系统上运行了该代码的基准测试。我知道Parallel Computing Toolbox gpuArray比CPU慢,但是Jacket和ArrayFire却差强人意。硬件规格为:

some benchmarks

使用Parallel Computing Toolbox gpuArray(完全预热)的CPU与GPU的结果。 CPU比PCT gpuArray更快]:

Intel(R) Xeon(R) CPU X5660  @ 2.80GHz
NVIDIA Tesla M2090

使用Jacket的CPU与GPU的结果(已完全预热)。 Jacket击败PCT gpuArray 3.7倍,CPU击败3X

>> tic; sqEuclideanDist(gpuArray(rand(1581,3)),gpuArray(rand(189,3))); toc;
Elapsed time is 0.006859 seconds.
>> tic; sqEuclideanDist(rand(1581,3),rand(189,3)); toc;
Elapsed time is 0.005712 seconds.

这是经过修改的代码,可让您轻松运行所有代码:

>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001876 seconds.

Jacket确实在GPU上支持BSXFUN,并且确实提高了速度:

function K = sqEuclideanDist(P,Q)
% Vectorized method to compute pairwise squared Euclidean distance on GPU
% Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:))

[nP, d] = size(P);
[nQ, d] = size(Q);

pmag = sum(P .* P, 2);
qmag = sum(Q .* Q, 2);

K = ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P*Q';

end

请注意,这里使用的大小非常小,因此大多数尝试在这些小尺寸上运行的CUDA代码的性能可能很差。这就是为什么我喜欢使用AccelerEyes的东西的原因,因为那些家伙已经优化了GPU的功能,这与我过去尝试过的PCT gpuArray,Thrust和OpenCV不同。

这里是ArrayFire Free C ++的结果:

>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001420 seconds.

这是我为此编写的ArrayFire代码:

Time:  0.0003577 seconds
Speedups:  19.2X faster than PCT gpuArray, 16X faster than the CPU, 5.2X faster
than Jacket in MATLAB original version, 4X faster than Jacket in MATLAB using
BSXFUN

1
投票

它们是由NVidia贡献的,因此在CUDA兼容卡上确实具有良好的性能。实际性能取决于卡本身和所使用的功能。

© www.soinside.com 2019 - 2024. All rights reserved.