Мой вопрос касается влияния передачи нескольких массивов в разных очередях асинхронизации между хостом и устройством.openacc - async - получение ускорения при передаче данных при использовании множества очередей асинхронизации
Предположим, у нас есть четыре массива:
double *a, *b, *c, *d;
И каждый из них был выделен с размером N
.
a = (double*) malloc(N * sizeof(double));
b = (double*) malloc(N * sizeof(double));
c = (double*) malloc(N * sizeof(double));
d = (double*) malloc(N * sizeof(double));
Теперь мы можем передавать их между устройством и хостом следующим образом в один пункте:
#pragma acc enter data copyin(a[0:N], b[0:N], c[0:N], d[0:N]) async
#pragma acc wait
Или мы можем использовать много асинхронных положений и передавать их по разным очередям:
#pragma acc enter data copyin(a[0:N]) async(1)
#pragma acc enter data copyin(b[0:N]) async(2)
#pragma acc enter data copyin(c[0:N]) async(3)
#pragma acc enter data copyin(d[0:N]) async(4)
#pragma acc wait
Результаты обоих вышеуказанных подходов являются одинаковыми. Однако с точки зрения производительности, второй, по-видимому, лучше в некоторых случаях.
Я сделал некоторые измерения и обнаружил, что для copyout
ING и обновления хоста кажется, что использование more
чем одной очереди лучше one
с точкой зрения производительности.
Давай называть первый подходом one
, а второй подходом more
, и следующий подходом more_nonumber
(не заметить никакого номера для пункта асинхронного):
#pragma acc enter data copyin(a[0:N]) async
#pragma acc enter data copyin(b[0:N]) async
#pragma acc enter data copyin(c[0:N]) async
#pragma acc enter data copyin(d[0:N]) async
#pragma acc wait
Тогда здесь измерения для 10000 итераций (за исключением 100 первых и 100 последних из них, что приводит к средним 9,800 итераций между ними):
one
CopyIn: 64.273us
Обновление устройства: 60.928us
Обновление самостоятельно: 69.502us
CopyOut: 70.929us
more
CopyIn: 65.944us
Обновление устройства: 62.271us
Обновление самостоятельно: 60.592us
CopyOut: 59.565us
more_nonumber
CopyIn: 66.018us
Обновление устройства: 62.735us
Update самостоятельно: 70.862us
CopyOut: 72.317us
Средняя 9800 работает!
При использовании метода more
для копирования (70.929/59.565) наблюдается ускорение в сравнении с one
или 14% для самообслуживания (69.502/60.592).
Мой вопрос: Являются ли эти цифры законными? Можем ли мы полагаться на эти цифры?
Для вашего удобства я поставил свой код на github. Вы можете взглянуть на него.
Еще раз спасибо Mat для всестороннего ответа. В вашей системе с закрепленной памятью побеждает ** один ** метод. Тем не менее, в моей системе, используя закрепленную память, ** больше ** лучше и получает больше ускорения! (PGI 16.5 - Geforce GTX 970 - CUDA 7.5 - CC 5.0) ---- У меня есть еще один вопрос относительно закрепленной памяти: так, можем ли мы сказать, что если программа/алгоритм связана с памятью, закрепленная память поможет в производительности, поскольку дополнительная память выполняется операция. – Millad
Для меня привязка к памяти означает, что алгоритм тратит больше времени на ожидание памяти, чем на вычисления, что приводит к простоя процессора. Что помогает связанным с памятью проблемам на графическом процессоре, так это добавить больше потоков, чтобы в то время как один поток ожидал памяти, другой может работать. Не то, что закрепленная память не могла не справиться с проблемой привязки памяти к главному процессору (без обмена страницами), в этом контексте я не думаю, что эти два связаны друг с другом, поэтому не будет делать эту корреляцию. –