Как я могу сравнить множество векторов друг с другом в CUDA (эффективно) - PullRequest
0 голосов
/ 07 июня 2018

Intro

Я пытаюсь написать программу, которая сравнивает векторы друг с другом.Мне нужно, чтобы он сравнивал каждый вектор с любым другим вектором и возвращал вектор c, где c [i] = a [i] / b [i].Поэтому мне нужен вектор C для каждой пары векторов в наборе.

Код - упрощенный

__global__
void compare_vectors(*a, *b, *c)  
    { c[ i ]  =  a[ i ] / b[ i ]  }

main()

    for(... all vectors...)  
        compare_vectors <<< grid, block >>> (n, n+1, result)

Проблема

Моя проблема в том, что делать это медленнее, чемэто на процессоре.Каждый раз, когда я повторяю цикл for, два вектора сравнения копируются в память устройства, а затем вектор результата копируется обратно в память хоста.

Я хочу иметь возможность сравнивать каждый вектор с каждым другим, но делать это эффективно, а затем копировать все результаты сразу.Как я могу структурировать это так, чтобы не было так много вызовов cudaMemcpy?

Информация
Я новичок в CUDA, поэтому, пожалуйста, будьте милостивы, если это супер очевидно.

Я прошел через несколько уроков и искал вокруг.Но все остальные примеры, кажется, сравнивают два очень длинных вектора, а не множество меньших векторов.Я много занимался поиском и исследованием, но не могу найти способ сделать это.

У меня есть около 2000 векторов для сравнения.И каждый вектор сравнивается с любым другим вектором.Итак, ~ 2000 ^ 2 сравнений.Каждый вектор длиной от 100 до 200 поплавков.

Спасибо @MartinBonner и @ platinum95.Рисование на сетке сделало вещи более ясными.

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

tl; dr: не делайте этого на (дискретном) графическом процессоре

Как предполагает @talonmies, эта проблема не подходит для использования графического процессора в качестве сопроцессора.

Вы видитена платформах Intel карта GPU не имеет такого же доступа к основной памяти, как процессор;данные должны быть отправлены на него по шине PCIe, пропускная способность которой значительно ниже (типичные значения: 12 ГБ / с против 30-40 ГБ / с для доступа к ЦП).Таким образом, хотя графический процессор может выполнять вычисления быстрее, чем центральный процессор, вы начнете видеть преимущества только в том случае, если их «плотность» относительно объема данных, над которыми вы работаете, достаточно высока.

В вашем случае вы передали бы вектор для каждой пары векторов, которые вы сравниваете.Даже если бы графический процессор выполнял все свои вычисления мгновенно, в 0 раз, он все равно работал бы медленнее, чем ЦП, из-за необходимости копировать результаты обратно.

(Кроме того, я действительно сомневаюсь, что вам нужны n * (n-1) / 2 вектора, это звучит странно.)

0 голосов
/ 07 июня 2018

Вы должны скопировать все векторы из CPU в память устройства, используя один вызов cudaMemcpy, а затем вычислить все деления в одном вызове ядра.В ядре вы можете запустить один поток на каждый вектор, а затем этот поток перебирает все остальные векторы и вычисляет результаты деления.Если ваш графический процессор поддерживает более 2000 потоков, вам следует изменить алгоритм так, чтобы поток повторял не все другие векторы, а только 1/10th из них, а затем остальные 9 потоков повторяли 1/10th вектора.

ОБНОВЛЕНИЕ: вам не нужно переносить каждую пару с процессора на графический процессор.Просто создайте массив с пространством, достаточным для хранения всех ваших N векторов, каждый M элементов в длину, затем на процессоре скопируйте N*M элементов один за другим в этот массив, затем вызовите cudaMemcpy, чтобы получить этот массив и на GPU.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...