Cupy Масштабирование timeit

Я пытаюсь эффективно рассчитать на GPU с помощью cupy.

В моем конкретном приложении время выполнения зависит от количества запусков (естественно). Однако не прямолинейно, а линейно с сначала небольшим наклоном, затем большим наклоном. Убедитесь сами: Билинейное увеличение времени выполнения с количеством выполнений

Мой вопрос: почему так?

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

Вот код того, как я измерил время

import cupy as cp
n = 401
s = 100
p = 100
x = cp.linspace(-5, 5, n, dtype=cp.float32)[:, cp.newaxis].repeat(s, 1)
sig = cp.random.uniform(.2, .4, (s, p), dtype=cp.float32)
a = cp.random.uniform(1, 2, (s, p), dtype=cp.float32)
c = cp.random.uniform(-3, 3, (s, p), dtype=cp.float32)


def cp_g(x, a, c, s):
    return cp.sum(cp.multiply(cp.exp(-cp.square(((x[...,cp.newaxis] - c) / s))), a * s / cp.sqrt(cp.float32(cp.pi))),axis=-1)


for i in cp.arange(10,1000,10):
     timeit('y= cp_g(x,a,c,sig)', globals=globals(), number=int(i))

P.S.: Если интересно, я использую железо GeForce 1660 Super. Куда 10.2. Python 3.7.0 (v3.7.0:1bf9cc5093, 27 июня 2018 г., 04:59:51) [MSC v.1914 64 бит (AMD64)]


person Patrick Lömker    schedule 04.08.2020    source источник
comment
Это потому, что вы не учли время GPU. Для этого необходимо синхронизировать устройство: timeit('y= cp_g(x,a,c,sig); cp.cuda.Device().synchronize()', ...). Это повлечет за собой небольшие накладные расходы, но они будут добавлены ко всем запускам, поэтому сравнение между запусками все равно будет справедливым.   -  person Leo Fang    schedule 04.08.2020


Ответы (1)


Такое поведение легко понять!

Timeit блокируется до тех пор, пока поток процессора не вернется. Однако это не учитывает время GPU. Для этого нужно добавить одну строку кода к вызову timeit

timeit('y= cp_g(x,a,c,sig); cp.cuda.Device().synchronize()', ...)

Спасибо Лео Фанг за комментарий!

person Patrick Lömker    schedule 06.08.2020