Постоянство буфера GPU при копировании Halide и SLOW между хостом и GPU - PullRequest
0 голосов
/ 26 марта 2020

У меня есть алгоритм, встроенный в галогенид. Я портирую эти алгоритмы из кода GPU, указанного c. На высоком уровне я построил объект-оболочку вокруг реализации halide, чтобы я мог хранить ссылки на объекты Halide :: Buffer. Я сделал это так, чтобы, надеюсь, входные и выходные буферы обходились без перераспределения между последовательными запусками алгоритма галогенида. Чтобы вставить новые данные в буфер, я выполняю memcpy в Buffer с помощью буфера .get () -> data () (который выставляет необработанный указатель на местоположение данных).

Что интересно is:

  1. Алгоритм / расписание моего галоидного процессора работает быстрее, чем наш собственный оптимизированный код GPU. Не секрет, что это не очень сложный алгоритм, и реализация GPU переносит 2 передачи данных, которые не требуются ЦПУ. Интересно то, что запланированная реализация графического процессора Halide медленнее, чем собственная реализация графического процессора. Проведя некоторое исследование с использованием функции Target :: set_feature (Halide :: Target :: Debug), я обнаружил, что основной причиной синхронизации являются операции копирования, идущие с хоста на устройство и обратно. Отдельная синхронизация этих операций с использованием нашей пользовательской реализации графического процессора приводит к времени передачи ~ 40 мс для передачи данных в графический процессор и ~ 60 мс времени для вывода данных из графического процессора (1 изображение вверх и 1 изображение вниз). В результате общее время обработки нашего пользовательского кода составляет 140-160 мс. Те же временные параметры, взятые из выходных данных Halide Debug, приводят к ~ 310 мс при получении данных до графического процессора (однако Halide планирует 2 копии, 1 для входного изображения и еще один для выходного изображения; выходное изображение не нужно, поскольку мы перезаписываем каждый пиксель в любом случае), и ~ 250 мс для копии выходного изображения обратно на хост. Спрашивается, зачем спрашивать, ПОЧЕМУ галоидные передачи данных SOOOOOOO медленно получают данные в и из GPU (кстати, это не зависит от выбранной технологии GPU, я пробовал D3D, OpenCL и CUDA) ???

  2. Почему Halide принудительно применяет копирование буфера RESULT к графическому процессору? Я попытался с помощью, а не с использованием .fill в этом буфере результатов. Без этого я не вижу копию на устройство при первом запуске, но потом я вижу копию на устройство при каждом последующем запуске (скорее всего потому, что когда оно копируется, Halide :: Buffer помечает устройство как «грязный», но данные все еще существуют в самом буфере, поэтому он хочет их скопировать. Проблема здесь в том, что нет способа явно пометить устройство как «чистое», чтобы избежать копирования на устройство.

  3. Даже если мой второй вопрос можно исправить, другая проблема заключается в том, что кажется, что копирование из операции «устройство-хост» автоматически вызывает освобождение устройства (что странно, потому что он НЕ делает этого для входной буфер, конечно, я НЕ делаю копию обратно во входной буфер.) Так как я могу выполнить копирование с устройства БЕЗ автоматической пометки его как «грязного» или автоматического его освобождения?

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

Извинения за без кода: проприетарный

ОБНОВЛЕНИЕ: После довольно большой работы я выяснил пару вещей: я сейчас использую версию релиза windows .dll-файла, что приводит к лучшему (хотя и не fantasti c) время передачи между хостом и графическим процессором (или наоборот).

В моем объекте я теперь поместил метод «как» передачи на хост, который проверяет распределение устройств, передает только вниз, когда есть на самом деле распределение устройств и оставляет любое устройство для размещения передает OUT любой из истинной реализации. Это позволяет пользователю переводить вниз, когда он sh (я сделал это таким образом, потому что я хотел сгруппировать передачу с установщиком источника set_min до возвращения пользователю).

С этим сказано Теперь у меня есть фактическое время выполнения, равное или меньше нашего настраиваемого ядра ЦП.

Чего это НЕ решает, так это того, что время передачи между хостом и графическим процессором мультипликативно больше, чем при использовании графического процессора. Прямые вызовы API, NOR - возможность устанавливать грязное устройство только тогда, когда я sh. То, что я перенесу буфер в ЦПУ, НЕ означает, что я его загрязняю, или что я не могу освободить его от устройства !!!

Я пытаюсь остаться как аппаратное агенство c, насколько я могу, поэтому я пытаюсь использовать объект Buffer как есть, чтобы НЕ использовать галогенид, предоставьте CUDA, OpenCL, Direct3D и т. д. c ... распределители устройств и т. д. c. ..

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