سؤال

لقد كنت أتجول في كتابة وحدات cffi بلغة python، وسرعتها تجعلني أتساءل عما إذا كنت أستخدم لغة python القياسية بشكل صحيح.إنه يجعلني أرغب في التبديل إلى لغة C تمامًا!بصدق، هناك بعض مكتبات بايثون الرائعة التي لم أتمكن أبدًا من إعادة تطبيقها بنفسي في لغة C، لذا فإن هذا أمر افتراضي أكثر من أي شيء آخر حقًا.

يوضح هذا المثال الدالة sum في لغة python المستخدمة مع مصفوفة numpy، ومدى بطئها بالمقارنة مع دالة c.هل هناك طريقة بايثونية أسرع لحساب مجموع مصفوفة numpy؟

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 بالطريقة الصحيحة؟هل هناك طريقة أسرع لحساب المبلغ في بيثون؟

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

مرات:

cffi 0.818415880203
numpy 5.61657714844
هل كانت مفيدة؟

المحلول

Numpy أبطأ من C لسببين:النفقات العامة لـ Python (ربما تشبه cffi) والعمومية.تم تصميم Numpy للتعامل مع صفائف ذات أبعاد عشوائية، في مجموعة من أنواع البيانات المختلفة.تم إنشاء المثال الخاص بك مع cffi لمجموعة ثنائية الأبعاد من العوامات.وكانت التكلفة كتابة عدة أسطر من التعليمات البرمجية مقابل .sum(), ، 6 أحرف لتوفير أقل من 5 ميكروثانية.(ولكن بالطبع، كنت تعرف هذا بالفعل).أريد فقط التأكيد على أن وقت وحدة المعالجة المركزية رخيص، وأرخص بكثير من وقت المطور.

الآن، إذا كنت تريد الاستمرار في Numpy، وترغب في الحصول على أداء أفضل، فإن أفضل خيار لك هو استخدامه عنق الزجاجة.إنها توفر بعض الوظائف المحسنة لمصفوفات 1 و2D من التعويم والمضاعف، وهي سريعة جدًا.في حالتك، أسرع بـ 16 مرة، مما سيضع وقت التنفيذ في 0.35، أو حوالي ضعف سرعة cffi.

بالنسبة للوظائف الأخرى التي لا يوجد بها عنق الزجاجة، يمكنك استخدام Cython.يساعدك على كتابة كود C باستخدام بناء جملة أكثر بيثونية.أو، إذا أردت، قم بتحويل لغة Python تدريجيًا إلى لغة C حتى تشعر بالرضا عن السرعة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top