Я считаю, что ArrayFire работает намного быстрее, и начал использовать его вместо ядер графического процессора в OpenCV для обработки изображений. Вот некоторые тесты Я обнаружил, что сравниваю ArrayFire (раньше он был в другом интерфейсе, называемом LibJacket) с OpenCV, и в моем бенчмаркинге также было верно, что ArrayFire в 2-4 раза быстрее, чем функции графического процессора в OpenCV. Из того, что я слышал, NVIDIA не писала ядра графического процессора в OpenCV, а передала их кому-то, возможно, поэтому они такие медленные. Поскольку я использую только 1 графический процессор, я могу использовать ArrayFire бесплатно.
Обновление, учитывая новый код MATLAB, опубликованный @Alex: я выполнил тест этого кода в своей системе. Я понимаю, что gpuArray в Parallel Computing Toolbox работает медленнее, чем CPU, но Jacket и ArrayFire пинают приклад. Технические характеристики аппаратного обеспечения:
Intel(R) Xeon(R) CPU X5660 @ 2.80GHz
NVIDIA Tesla M2090
Результаты сравнения процессора и графического процессора с использованием Parallel Computing Toolbox gpuArray (полностью прогретый). ЦП быстрее, чем 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.
Результаты сравнения процессора и графического процессора с использованием оболочки (полностью прогретой). Jacket превосходит PCT gpuArray в 3,7 раза и превосходит ЦП в 3 раза
>> 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 на графическом процессоре и несколько повышает скорость:
>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc;
Elapsed time is 0.001420 seconds.
Обратите внимание, что размеры, используемые здесь, довольно малы, поэтому большая часть кода CUDA, который пытается работать с этими небольшими размерами, скорее всего, будет работать плохо. Вот почему мне нравится использовать продукты AccelerEyes, потому что эти ребята чертовски оптимизировали GPU, в отличие от 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;
}
person
Ben Stewart
schedule
29.06.2012
[nP, d] = size(P_gpu);
[nQ, d] = size(Q_gpu);
даетnP = 1581
,nQ = 189
иd = 3
- person Alexey   schedule 29.06.2012