Обновить

Комментарии 1

Каждому отдельному потоку (треду) на GPU выдаются свои координаты в трехмерной сетке. Из координаты nw мы вытягиваем индекс картинки в батче n и индекс конкретного канала c (ведь у нас Depthwise-свёртка, канал обрабатывается изолированно). Координаты row и col — это пиксель (строка и столбец) на нашей выходной картинке.


Это вы свёртки ускоряли на GPU? Вот так?

Два цикла бегут по окну 3х3. Внутри стоит жесткая проверка: если мы вылезли за границы картинки (в те самые области паддинга), мы просто ничего не делаем (считаем, что там виртуальный ноль). Если мы внутри картинки, то считаем плоский индекс в памяти inp_idx (привет, channel-last формат NHWC), забираем значение пикселя, умножаем на вес из w и докидываем в общую копилку sum_val.

Если у вас GPU, то не надо так делать - это крайне медленно. Ваша задача свести свёртку к умножению тензоров. Эта та операция, которую GPU делает лучше всего. Либо на CUDA-ядрах с разделяемой памятью, либо на тензорных тоже с ней же. Это для произвольного ядра, конечно. Алгоритмы типа Винограда для фиксированных ядер работают быстрее.
Так вот, вот моя реализация всей обвязки свёрток и прочей математики на CUDA/тензорных ядрах вот такая вот (там внутри GAN, VAE, диффузионная сеть - во что компилируется выбирается в cuda.cu).
Там в файле ctensormath.cu.h реализация абстрактного умножения тензоров, а в файле ctensorconv.cu.h свёртки, обратные свёртки и расчёт обратного распространения через них.

Одна беда - я уже забыл, как эти картинки расшифровываются. :-D Хотя сам их и рисовал для понятности для себя. :-D
Там суть умножения в том, что вот эти вот матрицы не хранятся, а их элементы получаются и записываются "на лету" через STensorKernel - это такая абстрактная обёртка над свёрточными ядрами, матрицами весов, тензорами поправок ядер и так далее (их там несколько таких классов). То есть, умножения выполняются с тензорами STensorKernel нужного типа, а они уже сами раскидывают координаты умножаемых матриц в нужные объекты, к которым привязаны и выдают нужный элемент с учётом шага, дополнения, размера ядер и так далее.

А да, там, кстати, можно и на CPU-версию переключиться в settings.h. Там свёртки сделаны не через умножение, а циклами.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации