Ich finde ArrayFire viel schneller und habe begonnen, es anstelle der GPU-Kernel in OpenCV für die Bildverarbeitung zu verwenden. Hier sind some benchmarks Ich fand ArrayFire vergleichen (früher in einer anderen Schnittstelle namens LibJacket) zu OpenCV und es war auch in meinem Benchmark wahr, dass ArrayFire 2-4X schneller ist als die GPU-Funktionen in OpenCV. Von dem, was ich höre, hat NVIDIA die GPU-Kernel in OpenCV nicht geschrieben, sondern sie an jemanden vergeben, was vielleicht der Grund dafür ist, dass sie so langsam sind. Da ich nur 1 GPU verwende, kann ich ArrayFire kostenlos nutzen.
Update, angesichts der neuen MATLAB-Code von @Alex: Ich lief den Benchmark dieses Codes auf meinem System. Ich bekomme, dass die Parallel Computing Toolbox gpuArray langsamer als die CPU ist, aber Jacket und ArrayFire Kick Butt. HW-Spezifikationen sind:
Intel(R) Xeon(R) CPU X5660 @ 2.80GHz
NVIDIA Tesla M2090
Ergebnisse CPU vs GPU Parallel Computing Toolbox gpuArray (vollständig aufgewärmt) verwendet wird. CPU ist schneller als PCT gpuArray:
>> 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.
Ergebnisse CPU vs GPU mit Jacke (vollständig aufgewärmt). Jacke schlägt PCT gpuArray von 3.7X und schlägt die CPU von 3X
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001876 seconds.
Hier ist der modifizierte Code, dass wir Sie alle laufen, die leicht:
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
Jacke hat Unterstützung BSXFUN auf der GPU, und es macht die Geschwindigkeiten etwas verbessern :
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001420 seconds.
Beachten Sie, dass die Größen hier sind ziemlich klein verwendet, so dass die meisten CUDA-Code, der auf diesen kleinen Größen zu laufen versucht wahrscheinlich schlecht abschneiden. Deshalb benutze ich gerne AccelerEyes 'Zeug, weil diese Jungs das Beste aus der GPU gemacht haben, im Gegensatz zu PCT gpuArray, Thrust, OpenCV, die ich in der Vergangenheit probiert habe.
Hier die Ergebnisse ++ ArrayFire Freie C:
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
Hier wird der ArrayFire Code, den ich für diese schrieb:
static array SqEuclideanDist(array P, array Q)
{
// 0 based indexing
array pmag = sum(P * P, 1);
array qmag = sum(Q * Q, 1);
int np = P.dims(0);
int nq = Q.dims(0);
array K = tile(qmag.T(), np, 1) * tile(pmag, 1, nq) - 2 * matmul(P, Q.T());
return K;
}
int main(int argc, char **argv)
{
double *P_cpu = new double[1581 * 3];
double *Q_cpu = new double[189 * 3];
array P = array(1581, 3, P_cpu);
array Q = array(189 , 3, Q_cpu);
af::sync();
int iter = 1000;
timer::tic();
for (int i = 0; i < iter; i++) {
array K = SqEuclideanDist(P, Q);
af::eval(K);
}
af::sync();
printf("Time taken: %2.4lfms\n", (1000 * timer::toc())/iter);
delete[] P_cpu;
delete[] Q_cpu;
}
Welche Funktionen insbesondere erwägen Sie verwenden? –
Grundlegende Matrix Zeug. gpu :: reduzieren, gpu :: multiplizieren (pro Element Matrix Multiplikation). Auch Matrixmultiplikation, Finden von Matrixeigenwerten und Eigenvektoren, Matrixtransponierung. – Alexey
@Alex - alle einfachen Matrix Ops verwenden die NVidia (Schub?) Bibliothek direkt, so sind sehr gut optimiert –