Я нахожу ArrayFire намного быстрее и начал использовать его вместо ядер графического процессора в OpenCV для обработки изображений. Вот some benchmarks Я нашел сравнение ArrayFire (используемого в другом интерфейсе под названием LibJacket) для OpenCV, и это было верно и в моем бенчмаркинге, что ArrayFire на 2-4 раза быстрее, чем функции GPU в OpenCV. Из того, что я слышал, NVIDIA не записывала ядра GPU в OpenCV, но навязывала их кому-то, и, возможно, поэтому они настолько медленны. Поскольку я использую только 1 графический процессор, я могу использовать ArrayFire бесплатно.
Обновление, учитывая новый код MATLAB, отправленный @Alex: Я запустил эталон этого кода в своей системе. Я получаю, что Parallel Computing Toolbox gpuArray медленнее, чем процессор, но Jacket и ArrayFire. HW спецификации:
Intel(R) Xeon(R) CPU X5660 @ 2.80GHz
NVIDIA Tesla M2090
Результаты CPU против GPU с использованием параллельных вычислительных Toolbox gpuArray (полностью подогреваемый). процессор быстрее, чем РСТ 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.
Результаты CPU против GPU с использованием Jacket (полностью подогреваемый). Куртка бьет PCT gpuArray на 3.7X и бьет CPU по 3X
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001876 seconds.
Вот измененный код, который позволяет вам запускать все, что легко:
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
куртка делает поддержку BSXFUN на GPU, и это делает улучшить скорость несколько :
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001420 seconds.
Обратите внимание, что размеры, используемые здесь довольно малы, поэтому большинство CU код, который пытается работать на этих небольших размерах, вероятно, плохо работает. Вот почему я люблю использовать материалы AccelerEyes, потому что эти ребята оптимизировали черту из графического процессора, в отличие от PCT gpuArray, Thrust, OpenCV, каждый из которых я пытался в прошлом.
Вот в ArrayFire Free 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
Вот код ArrayFire я написал для этого:
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;
}
Какие функции, в частности, вы планируете использовать? –
Базовая матрица. gpu :: reduce, gpu :: multiply (на умножение матрицы элементов). Кроме того, матричное умножение, нахождение матричных собственных значений и собственных векторов, матрица транспонирована. – Alexey
@Alex - все простые матричные операторы используют библиотеку NVidia (thrust?) Напрямую, поэтому очень хорошо оптимизированы –