помогите разобраться
1) что есть coalesing и как он достигается ?
Обращением в одном потоке к разным блокам памяти
threadID 1 for (i=0;i<10;i++){a[threadID+i*16] = b[threadID+i*16]*c[threadID+i*16]; }
threadID 2 for (i=0;i<10;i++){a[threadID+i*16] = b[threadID+i*16]*c[threadID+i*16]; }
или в одном потоке последовательно, но в каждом треде к разному блоку ?
threadID 1 for (i=0;i<10;i++){a[threadID*16+i] = b[threadID*16+i]*c[threadID*16+i]; }
threadID 2 for (i=0;i<10;i++){a[threadID*16+i] = b[threadID*16+i]*c[threadID*16+i]; }
2) что такое warp ?
Вот есть 10 блоков по 64 потока Warp будет браться последовательно т е с первого потока по 32 ? Warp'ы (в GTX 295 их вроде как 64) выполняются параллельно ? Как вычислить сколько нужно потоков чтобы загрузить варп (неужели в тупую, 64 варпа - количество потоков - 64*32)?
3) как вычислить простой синерджиков ?
Волков писал, но я не осилил как вычислить что ядра стоят на ожидании загрузки из памяти ?
4) какова оптимальная последовательность команд в ртх коде. Как я понял основа всей оптимизации в cudа - работа с памятью скрывающая латентность и удачный подбор хода команд. Например есть цикл for (i=0;i<10;i++) { a = b*c; } нужно ли сначала сбрасывать в регистры а потом перемножать или как лучше выполнять чтобы достичь максимальной скорости ?
что лучше 4 команды загрузки в регистры и потом операции над этими регистрами
a0=A0
a1=A1
a2=A2
a3=A3
c=a0*a1*a2*a3
или то что они совмещены не имеет значение ?
5) В Волкове есть упоминание что __synchrothread() можно совмещать с арифметическими операциями. Как совмещать ? До или после вызова ?
6) За счет чего вобще достигается максимальная произвоидельность (желательны примеры кода) ?
Может я еще что то упустил и забыл Буду рад коментариям по делу
Работа с шаред памятью ограничена ее объемом и не всегда ее удается прикрутить с выгодой для производительности
pragma unroll - весьма не эффективная штука
удали одну ветку
1) зависит от устройства. Тредов должно быть минимум 16, и они должны одновременно забирать данные из одного непрерывного выровненного куска памяти. См. Programming Guide, там разжевано.
2) Programming Guide, с. 71
6) См. примеры с сайты нвидиа
Вообще если занялся кудой, то Programming Guide должен выучить наизусть как минимум. После этого можешь начинать писать что-то :)
>1) что есть coalesing и как он достигается
каждые 16 потоков с подряд идущими threadId должны писать или читать по подряд идущим аресам с шагом в 4, 8 или 16 байт
при этом адреса начала групп из 16 потоков должны быть выровнены на определнную величину, но на это обычно положить, потому что cudaMalloc всегда возвращает выровненный по 256 байт поинтер.
>2) что такое warp ?
Объединение из 32 потоков. Можно считать, что это еденица исполнения, то есть все потоки внутри варпа выполняютя параллельно.
>выполняются параллельно ?
не гарантировано и не регламентировано, как именно выполняются варпы, но впринципе да- параллельно
> (в GTX 295 их вроде как 64)
чего 64? Варпы - это логическая еденица. не путай железо софт
>Как вычислить сколько нужно потоков - дальше у тебя идет бред.
Только опытным путем. Общее правило: их должно быть сильно больше, чем может одновременно исполняться на видеокарте. Скажем, в 10 раз больше.
>как вычислить простой синерджиков
простой кого? поясни пожалуйста о чем ты
>нужно ли сначала сбрасывать в регистры
регистры надо экономить.
>В Волкове есть упоминание что __synchrothread() можно совмещать с арифметическими операциями. Как совмещать ? До или после вызова ?
Покажи что за Волков такой?
6) За счет чего вобще достигается максимальная произвоидельность (желательны примеры кода) ?
По разному.
1) высокой занятости мультипроцессоров (нужно снижать количество регистров, занимаесых ядром) - 16-20. максимум 32 но не более.
2) соблюдения правил коалесинга.
3) Не стоит злоупотреблять текстурами.
red noise
> Вообще если занялся кудой, то Programming Guide должен выучить наизусть как
> минимум.
кто ж это программинг гуиды учит, а? ты б еще сказал - кто хочет писать на ассемблере должен выучить сначала все команды .386 и уж потом что-то писать
FROL
Это специфика куды.
А вот я бы уточнил пару моментов.
>1) высокой занятости мультипроцессоров (нужно снижать количество регистров, занимаесых ядром) - 16-20. максимум 32 но не более.
Тут дело не в регистрах, а в количестве микротредов (хотя конечно, количество используемых регистров влияет на количство микротредов, которое можно себе позволить). Чем больше микротредов, тем больше "вероятность" того, что мультипроцессору будет что исполнять, т.е. он не будет простаивать. Этим можно маскировать латентность памяти, например.
>3) Не стоит злоупотреблять текстурами.
Текстурами злоупотреблять как раз стоит. В cuda 2.2 добавили фичу, что "2D-текстурить" можно из 1D-памяти (а не только из 2D-памяти). Преимущество 2D-текстур есть в кэшировании данных как по строкам, так и по столбцам (т.е. если данные находятся пространственно рядом, будет профит во времени доступа), а также (отключаемая) билинейная фильтрация.
А чем CUDA лучше чем просто написать шейдер и отрисовать фулскрин квад?
Tonal
> А чем CUDA лучше чем просто написать шейдер и отрисовать фулскрин квад?
Как минимум - проще в организации приложения: не нужно создавать всякие вертекс-буферы, шейдер-менеджеры и прочее.
Просто написал функцию на CUDA и вызвал ее из С++ кода.
Wraith
> Текстурами злоупотреблять как раз стоит
Ну смотря что пишем. Вот в каких случаях я считаю не стоит (ок, вы можете быть не согласны):
1) когда каждый тред хочет свои данные и данные не перекрываются. Тогда нет смысла использовать кэш. А латентность текстурной памяти выше, чем глобальной.
2) когда данные перекрываются, но только внутри блоков и так, что можно эффективно использовать механизм раздачи shared памяти
И в конц конце концов - кэш не резиновый. На самом деле он очень маленький. Я имел ввиду, что не стоит делать много разных текстур с разными данными. лучше, если текстур поменьше и тогда эффективность от текстурного кэша выше. По крайней мере когда я заменил часть своих текстур на обращения к глобальной памяти с соблюдением коалесинга, программа стала работать в два раза быстрее.
еще раз переформулирую свою мысль. Если вам не нужен кэш, не нужны и текстуры.
По поводу занятости - да. Количество микротредов, одновременно работающих на видеокарте - ну оно зависит от трех вещей - количество занимаемых регистров, shared памяти, compute capability и конфигурация запуска. На последнее можно забить так как ее всегда можно подобрать ну compute capability понятно. shared памяти мне всегда хватало. А вот с регистрами беда страшная.
Тема в архиве.