Как вы оптимизируете этот код ( без векторизации, так как это приводит к использованию семантики вычисления, что довольно часто не является нетривиальным):
slow_lib.py:
import numpy as np
def foo():
size = 200
np.random.seed(1000031212)
bar = np.random.rand(size, size)
moo = np.zeros((size,size), dtype = np.float)
for i in range(0,size):
for j in range(0,size):
val = bar[j]
moo += np.outer(val, val)
Дело в том, что такие петли такого типа довольно часто соответствуют операциям, в которых у вас есть двойные суммы над некоторой векторной операцией.
Это довольно медленно:
>>t = timeit.timeit('foo()', 'from slow_lib import foo', number = 10)
>>print ("took: "+str(t))
took: 41.165681839
Итак, дайте cynothize и добавьте аннотации типа, которых нет завтра:
c_slow_lib.pyx:
import numpy as np
cimport numpy as np
import cython
@cython.boundscheck(False)
@cython.wraparound(False)
def foo():
cdef int size = 200
cdef int i,j
np.random.seed(1000031212)
cdef np.ndarray[np.double_t, ndim=2] bar = np.random.rand(size, size)
cdef np.ndarray[np.double_t, ndim=2] moo = np.zeros((size,size), dtype = np.float)
cdef np.ndarray[np.double_t, ndim=1] val
for i in xrange(0,size):
for j in xrange(0,size):
val = bar[j]
moo += np.outer(val, val)
>>t = timeit.timeit('foo()', 'from c_slow_lib import foo', number = 10)
>>print ("took: "+str(t))
took: 42.3104710579
... эх... что? Numba на помощь!
numba_slow_lib.py:
import numpy as np
from numba import jit
size = 200
np.random.seed(1000031212)
bar = np.random.rand(size, size)
@jit
def foo():
bar = np.random.rand(size, size)
moo = np.zeros((size,size), dtype = np.float)
for i in range(0,size):
for j in range(0,size):
val = bar[j]
moo += np.outer(val, val)
>>t = timeit.timeit('foo()', 'from numba_slow_lib import foo', number = 10)
>>print("took: "+str(t))
took: 40.7327859402
Так нет способа ускорить это? Дело в том, что:
- Если я преобразую внутренний цикл в векторизованную версию (создаю большую матрицу, представляющую внутренний цикл, а затем вызываю np.outer на более крупной матрице), я получаю гораздо более быстрый код.
- , если я реализую нечто подобное в Matlab (R2016a), это довольно хорошо выполняется из-за JIT.