Вопрос

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

В этом примере показан функция суммы в Python, используемой с помощью Numpy Array, и насколько медленно его по сравнению с функцией C.Есть ли более быстрый питонический способ вычислительной суммы разменного массива?

def cast_matrix(matrix, ffi):
    ap = ffi.new("double* [%d]" % (matrix.shape[0]))
    ptr = ffi.cast("double *", matrix.ctypes.data)
    for i in range(matrix.shape[0]):
        ap[i] = ptr + i*matrix.shape[1]                                                                
    return ap 

ffi = FFI()
ffi.cdef("""
double sum(double**, int, int);
""")
C = ffi.verify("""
double sum(double** matrix,int x, int y){
    int i, j; 
    double sum = 0.0;
    for (i=0; i<x; i++){
        for (j=0; j<y; j++){
            sum = sum + matrix[i][j];
        }
    }
    return(sum);
}
""")
m = np.ones(shape=(10,10))
print 'numpy says', m.sum()

m_p = cast_matrix(m, ffi)

sm = C.sum(m_p, m.shape[0], m.shape[1])
print 'cffi says', sm
.

Просто чтобы показать функцию работы:

numpy says 100.0
cffi says 100.0
.

Теперь, если мне время эта простая функция, я нахожу, что Numpy действительно медленно! Я использую Numpy правильно?Есть ли более быстрый способ рассчитать сумму в Python?

import time
n = 1000000

t0 = time.time()
for i in range(n): C.sum(m_p, m.shape[0], m.shape[1])
t1 = time.time()

print 'cffi', t1-t0

t0 = time.time()
for i in range(n): m.sum()
t1 = time.time()

print 'numpy', t1-t0
.

Times:

cffi 0.818415880203
numpy 5.61657714844
.

Это было полезно?

Решение

Numpy медленнее, чем C по двум причинам: накладные расходы на питон (вероятно, похоже на CFFI) и общности. NUMPY предназначен для решения массивов произвольных измерений, в кучу различных типов данных. Ваш пример с CFFI был сделан для 2D-массива поплавков. Стоимость писала несколько строк кода VS .sum(), 6 символов, чтобы сохранить менее 5 микросекунд. (Но, конечно, вы уже знали это). Я просто хочу подчеркнуть, что время ЦП дешево, намного дешевле, чем время разработчика.

Теперь, если вы хотите придерживаться numpy, и вы хотите получить лучшую производительность, ваш лучший вариант должен использовать Узкое место . Они обеспечивают несколько функций, оптимизированных для 1 и 2D массивов поплавка и удваивает, и они быстро продувают. В вашем случае, в 16 раз быстрее, что укажет время выполнения в 0,35 или примерно в два раза быстрее, чем CFFi.

Для других функций, которые не имеют узкого места, вы можете использовать Cython. Это поможет вам писать C код с более синтаксисом Pythonic. Или, если вы будете преобразовать постепенно Python в C, пока вы не будете довольны скоростью.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top