Как добиться более быстрого convolve2d с помощью графического процессора - PullRequest
2 голосов
/ 04 марта 2020

Я недавно изучал PyCuda и планировал заменить некоторый код системы камер для ускорения обработки изображений. Эта часть первоначально использовала cv2.filter2D . Я намерен ускорить обработку с помощью графического процессора.

Time for signal.convolve2d: 1.6639747619628906
Time for cusignal.convolve2d: 0.6955723762512207
Time for cv2.filter2D: 0.18787837028503418

Однако, похоже, что cv2.filter2D по-прежнему самый быстрый из трех. Если ввод представляет собой длинный список изображений, может ли пользовательское ядро ​​PyCuda перевесить cv2.filter2D?

import time
import cv2
from cusignal.test.utils import array_equal
import cusignal
import cupy as cp
import numpy as np
from scipy import signal
from scipy import misc
ascent = misc.ascent()
ascent = np.array(ascent, dtype='int16')

ascentList = [ascent]*100

filterSize = 3
scharr = np.ones((filterSize, filterSize), dtype="float") * (1.0 / (filterSize*filterSize))

startTime = time.time()
for asc in ascentList:
    grad = signal.convolve2d(asc, scharr, boundary='symm', mode='same')
endTime = time.time()
print("Time for signal.convolve2d: "+str(endTime - startTime))

startTime = time.time()
for asc in ascentList:
    gpu_convolve2d = cp.asnumpy(cusignal.convolve2d(cp.asarray(asc), scharr, boundary='symm', mode='same'))
endTime = time.time()
print("Time for cusignal.convolve2d: "+str(endTime - startTime))
print("If signal equal to cusignal: "+ str(array_equal(grad, gpu_convolve2d)))

startTime = time.time()
for asc in ascentList:
    opencvOutput = cv2.filter2D(asc, -1, scharr)
endTime = time.time()
print("Time for cv2.filter2D: "+str(endTime - startTime))
print("If cv2 equal to cusignal: "+ str(array_equal(opencvOutput, gpu_convolve2d)))

1 Ответ

1 голос
/ 06 марта 2020
  1. При анализе синхронизации GPU вы определяете время для копирования asc в GPU, выполнения convolve2d и передачи ответа обратно. Передачи в и из GPU очень медленные в схеме вещей. Если вы хотите истинное сравнение вычислений, просто профиль convolve2d.

  2. В настоящее время cuSignal.convolve2d написано в Numba. Мы находимся в процессе переноса этого на использование CuPy Raw Kernels, и будет улучшение. У меня нет ETA на convolve2d.

  3. Похоже, что может быть версия OpenCV CUDA https://github.com/opencv/opencv_contrib/blob/master/modules/cudafilters/src/cuda/filter2d.cu

  4. Вы пробовали scipy.ndimage.filters.convolve - http://blog.rtwilson.com/convolution-in-python-which-function-to-use/

  5. Также, проверьте CuPy's convolve - https://github.com/cupy/cupy/blob/master/cupyx/scipy/ndimage/filters.py

Теперь к вашему первоначальному вопросу. При попытке определить, будет ли графический процессор работать быстрее, чем центральный процессор, необходимо убедиться, что работы достаточно, чтобы она была занята. Известно, что в некоторых случаях, когда размер данных невелик, процессор будет работать быстрее.

...