Войти
ПрограммированиеФорумГрафика

Никак не могу придумать, как посчитать интенсивность изображения с помощью compute shader (2 стр)

Страницы: 1 2 3 Следующая »
#15
0:06, 12 июня 2016

ArchiDevil
> Текущий-то фрейм нужен мгновенно.
текущий фрейм может и ранее посчитанное значение для подгона яркости использовать, а компьют все равно асинхронный, так что данные из буфера куда компьют пишет можно будет забрать потом без всяких синхронизаций


#16
0:58, 12 июня 2016

ArchiDevil
> В конце-то всё равно еще пасс пускать, либо на CPU дергать это дело придется.
Чево-чево?

> Когда надо будет собрать аутпут с групп.
Делается барьер и дальше один из потоков группы собирает (или схема со сборкой сверткой). Т.е. типо так:

<compute>
Shared[threadID] := ThreadResult;
Barrier
If threadID = 0 Then 
 Begin
  Result := 0;
  For I := 0 to 63 do Result += Shared[I];
  FinalResult := Result;
 End;

#17
2:30, 12 июня 2016

както так

<compute>
Shared[threadID] := ThreadResult;
Barrier
 If threadID <32 Then 
  Shared[threadID]  += Shared[threadID+32] ;
  Barrier
  If threadID <16 Then Shared[threadID]  += Shared[threadID+16] ;
  If threadID <8 Then Shared[threadID]  += Shared[threadID+8] ;
  If threadID <4 Then Shared[threadID]  += Shared[threadID+4] ;
  If threadID <2 Then Shared[threadID]  += Shared[threadID+2] ;
  If threadID <1 Then Shared[threadID]  += Shared[threadID+1] ;
  FinalResult := Shared[0];
 end;

#18
2:36, 12 июня 2016

Bishop
> 64 потока в варпе обрабатывают каждый свою группу линий
А остальные мультипроцессоры простаивать будут?
Да и первый всего одним варпом загружен.

Так что запускать надо несколько десятков варпов, как минимум.
Каждый поток варпа считает свою сумму, затем двоичное усреднение в пределах варпа (синхронизация в этом случае, вообще, не нужна).
Если на одном мультипроцессоре больше одного варпа, то усреднение в пределах мультипроцессора (вот здесь синхронизация нужна).
Затем отдельный запуск, который собирает данные со всех мультипроцесооров.

#19
5:27, 12 июня 2016

susageP
У тебя ошибка. в твоём примере нужно ещё 4 барьера, а иначе будет черте что. Собственно именно из-за того что я не уверен в цене 4-х барьеров я и сказал о 2-х вариантах.

}:+()___ [Smile]
> А остальные мультипроцессоры простаивать будут?
Да (ну или заняты другими задачами, но не этой). Тут всё зависит от цены использования промежуточного буфера и синхронизации 2-х диспатчей. Потому я и привёл 2 варианта. Ну померять нужно что быстрее.

> затем двоичное усреднение в пределах варпа (синхронизация в этом случае,
> вообще, не нужна).
Лол что? В документаци чётко и ясно сказано что доступ в шаред-память надлежит синхронизировать.

>Если на одном мультипроцессоре больше одного варпа, то усреднение в пределах мультипроцессора (вот здесь синхронизация >нужна).
Это ещё что за ужас? Или мы используем разную теминологию, или это вообще невозможно (можно конечно извратиться с локом через глобальную память, но я даже хз сработает ли).

#20
6:31, 12 июня 2016

Bishop
> В документаци чётко и ясно сказано что доступ в шаред-память надлежит синхронизировать.
При доступе из разных варпов одной локальной группы одновременно.
В документации вполне может не быть понятия варпа (хотя в OpenCL точно есть), поэтому написали по-простому.

> Это ещё что за ужас? Или мы используем разную теминологию, или это вообще невозможно
Есть один SIMD поток — это варп, выполняться вразнобой команды физически не могут.
Есть несколько потоков на одном процессоре — это локальная группа с доступом к блоку общей локальной памяти, нужны примитивы синхронизации.
Есть разные процессоры, между которыми нормальной синхронизации нет.

#21
6:40, 12 июня 2016

}:+()___ [Smile]
> Есть один SIMD поток — это варп, выполняться вразнобой команды физически не
> могут.
> Есть несколько потоков на одном процессоре — это локальная группа с доступом к
> блоку общей локальной памяти, нужны примитивы синхронизации.
> Есть разные процессоры, между которыми нормальной синхронизации нет.
Так и думал, мы используем разную терминологию. В теме речь про compute shared. Не знаю как в OpenGL/Vulkan но в DirectX ситуация такая. Есть поток. Он является SIMD, причём более продвинутый чем у CPU, но это всё ещё именно один поток. Есть Warp, это группа потоков которую выполняет один мультипроцессор. У мультипроцессора единственный счётчик адреса, т.е. ВСЕ потоки мультипроцессора всегда выполняют одну и туже инструкцию (обработка ветвлений через маскирование - т.е. если хоть один поток варпа пошел в ветку - время тратит весь мультипроцессор). Ну и у видюшки несколько мультипроцессоров. Так я читал в доках вердоров. Т.е. Wrap это именно то, у чего его Shared память и что нужно синхронизировать.

P.S. Кстати ширина SIMD у потока максимум 4, т.е. никаких 64-х там и близко быть не может.

#22
12:04, 12 июня 2016

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

+ Показать

#23
13:44, 12 июня 2016

http://diaryofagraphicsprogrammer.blogspot.ru/2014/03/compute-sha… -for-amd.html

Вот здесь можно посмотреть алгоритмы для сложения внутри группы с замерами по времени.

#24
14:18, 12 июня 2016

Bishop
> Делается барьер и дальше один из потоков группы собирает (или схема со сборкой
> сверткой). Т.е. типо так:
Это да, а потом кто-то еще должен собрать аутпут со всех групп. Поэтому тут второй пасс нужен для прохода по всем буферам.

#25
19:41, 12 июня 2016

Попробовал вот такой шейдер. Вроде работает, если число потоков в группе не больше 32 (у меня nvidea).

+ Показать

#26
20:25, 12 июня 2016

Bishop
Это у тебя путаница. В разных API, конечно, есть небольшие различия, но в главных вещах они совпадают.
Варп везде где я видел — это один SIMD поток.

> У мультипроцессора единственный счётчик адреса, т.е. ВСЕ потоки мультипроцессора всегда выполняют одну и туже инструкцию
Вот это неверно. У одного SIMD потока один адрес выполнения, но на мультипроцессоре могут выполняться сразу несколько таких потоков (HyperThreading), в том числе из разных шейдеров.
Я когда экспериментировал, у меня было максимум 512 тредов на мультипроцессор с варпом 32 — т. е. 16 различных потоков, каждый со своим адресом.

> P.S. Кстати ширина SIMD у потока максимум 4, т.е. никаких 64-х там и близко быть не может.
Это ты с VLIW от AMD путаешь. У nvidia размер варпа 32, у AMD — 32 или 64, у Intel-а меньше, но тоже 8+.

#27
22:53, 12 июня 2016

ArchiDevil
> Это да, а потом кто-то еще должен собрать аутпут со всех групп. Поэтому тут
> второй пасс нужен для прохода по всем буферам.
Ну в одном из вариантов я говорил о том, что задействуется ТОЛЬКО ОДИН мультипроцессор.

__sergey
> Попробовал вот такой шейдер. Вроде работает, если число потоков в группе не
> больше 32 (у меня nvidea).
Ну причина описана в DX SDK.
> GroupMemoryBarrierWithGroupSync - Blocks execution of all threads in a group until all group shared accesses have been completed and all threads in the group have reached this call.
Фактически ничто не гарантирует что все потоки группы выполняются синхронно. Если ты вкладываешься в варп (кстати вспомнил таки, варп это кол-во потоков группы исполняемых одновременно, но GAPI работают не с вапрами, а с группами, потому синхронизация обазятельна) конкретного устройства, то это более-менее так. Но т.к. варпы различные + нужно больше потоков чтобы скрывать латентность доступа к памяти, то синхронизация всё равно нужна. Я просто помнил что на NVidia стабильно использовал 64 потока в группе, но не помнил почему именно. Наверное как раз уз-за латентности памяти.

}:+()___ [Smile]
> Вот это неверно. У одного SIMD потока один адрес выполнения, но на
> мультипроцессоре могут выполняться сразу несколько таких потоков
> (HyperThreading), в том числе из разных шейдеров.
> Я когда экспериментировал, у меня было максимум 512 тредов на мультипроцессор с
> варпом 32 — т. е. 16 различных потоков, каждый со своим адресом.
Да-да, я вспомнил детали. GAPI с варпом вообще не работает, потому то там и нет этого понятия. Там это называется ThreadGroup. Так что да, это я ошибся в терминах. Хотя суть того что для ThreadGroup в общем случае нужна синхронизация это не отменяет. Это тоже самое как многопоточность на CPU, в некоторых сценариях может работать вообще без синхронизации на конкретном железе просто потому что тайминги такие.

#28
23:24, 12 июня 2016

Bishop
> Фактически ничто не гарантирует что все потоки группы выполняются синхронно.
Наверное, раз нужна синхронизация, иначе барьеров вообще бы не было.

Bishop
> Ну причина описана в DX SDK.
> > GroupMemoryBarrierWithGroupSync - Blocks execution of all threads in a group
> > until all group shared accesses have been completed and all threads in the
> > group have reached this call.

Какое это имеет отношение к размеру фронта? Если сделать размер группы больше, то придется, возможно, в два последовательных захода ее просчитывать, хоть это и будет иметь вид одной группы, например 64, но скорей всего, на самом деле, это будет 2*32 и что-то там с логикой в шейдере с таким подходом не согласуется.

+ Показать
#29
21:02, 13 июня 2016

Сделал предлагаемый Bishopом подход за один пасс. Пришлось завести отдельный буфер интенсивностей под каждую линию текстуры, но это просто мелкие накладные расходы. С производительностью не парился, всё там тривиально.

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.