Cython automati c цикл развертывания - PullRequest
1 голос
/ 07 апреля 2020

Я пытаюсь ускорить часть кода Python, в котором у меня есть следующий код:

for i in range(n):
   for j in range(m):
       for (sign,idx) in [(a,b),(c,d),(e,f),(g,h)]:
           array[idx,i] += sign * something
           array[idx,j] += sign * somethingElse

, где a, b, c ... - относительно сложные выражения.

Если я вручную разверну для внутренней для l oop, написав:

for i in range(n):
   for j in range(m):
           sign,idx = a,b
           array[idx,i] += sign * something
           array[idx,j] += sign * somethingElse
           sign,idx = c,d
           array[idx,i] += sign * something
           array[idx,j] += sign * somethingElse
           sign,idx = e,f
           array[idx,i] += sign * something
           array[idx,j] += sign * somethingElse
           sign,idx = g,h
           array[idx,i] += sign * something
           array[idx,j] += sign * somethingElse

Код выполняется в 4 раза быстрее ... Но вставка копии кажется плохой идеей.

Мой вопрос: это можно сделать автоматически во время компиляции?

1 Ответ

0 голосов
/ 07 апреля 2020

Я предполагаю, что это действительно проблема ввода: в test1 () я явно создаю массив «values», а в test2 () я создаю этот массив каждый раз.

def test1():
    cdef int i
    cdef int value
    cdef int values[4]
    cdef double sum = 0
    values[:] = [1,2,3,4]
    for i in range(1000000):
        for value in values:
            sum += values[j]
    return sum

def test2():
    cdef int i
    cdef int value
    cdef double sum = 0
    for i in range(1000000):
        for value in [1,2,3,4]: 
            sum += value
    return sum

Первая версия примерно в 3 раза быстрее:

%timeit test1()
4.4 ms ± 44.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test2()
13.3 ms ± 44.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
...