Trovo che lo ArrayFire sia molto più veloce e che abbia iniziato ad usarlo al posto dei kernel GPU in OpenCV per l'elaborazione delle immagini. Qui ci sono some benchmarks Ho trovato il confronto tra ArrayFire (utilizzato in un'interfaccia diversa chiamata LibJacket) in OpenCV ed è stato vero anche nel mio benchmarking che ArrayFire è 2-4X più veloce delle funzioni GPU in OpenCV. Da quello che ho sentito, NVIDIA non ha scritto i kernel GPU in OpenCV ma li ha commissionati a qualcuno, il che potrebbe essere il motivo per cui sono così lenti. Dal momento che sto usando solo 1 GPU, posso usare ArrayFire gratuitamente.
Aggiornamento, dato il nuovo codice MATLAB pubblicato da @Alex: Ho eseguito il benchmark di questo codice sul mio sistema. Ho capito che il Parallel Computing Toolbox gpuArray è più lento della CPU, ma Jacket e ArrayFire. spec HW sono:
Intel(R) Xeon(R) CPU X5660 @ 2.80GHz
NVIDIA Tesla M2090
Risultati della CPU vs GPU utilizzando Parallel Computing Toolbox gpuArray (completamente riscaldato). CPU è più veloce di 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.
Risultati della CPU vs GPU utilizzando Jacket (completamente riscaldato). Jacket batte PCT gpuArray di 3.7X e batte la CPU da 3X
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001876 seconds.
Ecco il codice modificato che ti permette di eseguire tutti così facilmente:
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
Giacca fa supporto BSXFUN sulla GPU, e lo fa migliorare le velocità di un po ' :
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001420 seconds.
Nota che le dimensioni utilizzate qui sono piuttosto piccole, quindi la maggior parte del codice CUDA che tenta di funzionare su queste piccole dimensioni è probabile che scarso rendimento. È per questo che mi piace usare le cose di AccelerEyes, perché quei ragazzi hanno ottimizzato la GPU, a differenza di PCT gpuArray, Thrust, OpenCV, ognuno dei quali ho provato in passato.
Ecco l'ArrayFire libero C++ risultati:
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
Qui è il codice ArrayFire che ho scritto per questo:
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;
}
Quali funzioni, in particolare, si stanno prendendo in considerazione utilizzando? –
Materie di base. gpu :: reduce, gpu :: multiply (per moltiplicazione di matrice di elementi). Inoltre, moltiplicazione di matrici, individuazione di autovalori di matrice e autovettori, trasposizione di matrici. – Alexey
@Alex - tutte le semplici matrici utilizzano direttamente la libreria NVidia (thrust?) E quindi sono ottimizzate ottimamente –