Только передача графического процессора на процессор с помощью cupy невероятно медленная

#python #numpy #tensorflow #pytorch #cupy

Вопрос:

Если у меня есть массив на графическом процессоре, копирование массива формы (20, 256, 256) происходит очень медленно (порядка сотен секунд).

Мой код выглядит следующим образом:

 import cupy as cp from cupyx.scipy.ndimage import convolve import numpy as np  # Fast... xt = np.random.randint(0, 255, (20, 256, 256)).astype(np.float32) xt_gpu = cp.asarray(xt)  # Also very fast... result_gpu = convolve(xt_gpu, xt_gpu, mode='constant')  # Very very very very very slow.... result_cpu = cp.asnumpy(result_gpu)  

Я измерил время, используя cp.cuda.Event() record и synchronize , чтобы избежать измерения любого случайного времени, но результат все тот же, передача GPU-gt;CPU невероятно медленная. Однако при использовании PyTorch или TensorFlow это не так (из опыта для аналогичного размера/формы данных)… Что я делаю не так?

Ответ №1:

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

 import cupy as cp from cupyx.scipy.ndimage import convolve import numpy as np import time # Fast... xt = np.random.randint(0, 255, (20, 256, 256)).astype(np.float32)  t0 = time.time() xt_gpu = cp.asarray(xt) cp.cuda.stream.get_current_stream().synchronize() print(time.time() - t0)  # Also very fast... t0 = time.time() result_gpu = convolve(xt_gpu, xt_gpu, mode='constant') cp.cuda.stream.get_current_stream().synchronize() print(time.time() - t0)  # Very very very very very slow.... t0 = time.time() result_cpu = cp.asnumpy(result_gpu) cp.cuda.stream.get_current_stream().synchronize() print(time.time() - t0)  

Выход:

 0.1380000114440918 4.032999753952026 0.0010001659393310547  

Мне кажется, что вы на самом деле не синхронизируетесь между звонками, когда тестировали его. До тех пор, пока передача обратно в массив numpy, все операции просто ставятся в очередь и, кажется, завершаются мгновенно без вызовов синхронизации. Это приведет к тому, что измеренное время передачи GPU-gt;CPU фактически будет временем свертки и передачи.