<p>تنفيذ numpy.vectorize هو في الأساس حلقة for؟</p>

تم إنشاؤها على ٦ يوليو ٢٠٢٠  ·  5تعليقات  ·  مصدر: numpy/numpy

https://numpy.org/doc/1.18/reference/generated/numpy.vectorize.html
يذكر هذا البرنامج التعليمي أن تنفيذ Vectorize هو في الأساس حلقة for. ولكن بقدر ما أعرف ، سوف تستخدم func المتجه
SIMD ، فهل من الصحيح القول بأن تنفيذ numpy.vectorize هو في الأساس حلقة for؟ إذا كان هذا صحيحًا ، فهو أسرع من func غير المقيد فقط لأنه تم تنفيذ حلقة في لغة C؟

شكرا كثيرا مسبقا.

33 - Question

التعليق الأكثر فائدة

نعم. في سياق لغات برمجة المصفوفات الرقمية المفسرة مثل Python (مع numpy) و MATLAB ™ ، غالبًا ما نستخدم "Vectorization" للإشارة إلى استبدال الحلقات الصريحة في لغة البرمجة المفسرة بوظيفة (أو عامل) يهتم بكل من حلقات المنطق داخليا. في numpy ، يقوم ufunc s بتنفيذ هذا المنطق. هذا لا علاقة له باستخدام "vectorization" للإشارة إلى استخدام تعليمات SIMD CPU التي تحسب عبر مدخلات متعددة بشكل متزامن ، باستثناء أن كلاهما يستخدم استعارة مماثلة: إنهما مثل نظرائهما "القياسيين" ، لكنهما يؤديان الحساب على قيم إدخال متعددة بدعوة واحدة.

مع numpy.vectorize() ، لا يوجد عادةً الكثير من مزايا السرعة على حلقة Python for الصريحة. الهدف الرئيسي منها هو تحويل دالة Python إلى ufunc ، والتي تنفذ جميع دلالات البث وبالتالي تتعامل مع أي حجم من المدخلات. لا تزال وظيفة Python التي يتم "تحويلها" تستغرق معظم الوقت ، بالإضافة إلى تحويل القيمة الأولية لكل عنصر إلى كائن Python لتمريرها إلى الوظيفة. لا تتوقع أن يكون np.vectorize(lambda x, y: x + y) بنفس سرعة ufunc np.add ، وهو C في كل من الحلقة ومحتويات الحلقة.

ال 5 كومينتر

نعم. في سياق لغات برمجة المصفوفات الرقمية المفسرة مثل Python (مع numpy) و MATLAB ™ ، غالبًا ما نستخدم "Vectorization" للإشارة إلى استبدال الحلقات الصريحة في لغة البرمجة المفسرة بوظيفة (أو عامل) يهتم بكل من حلقات المنطق داخليا. في numpy ، يقوم ufunc s بتنفيذ هذا المنطق. هذا لا علاقة له باستخدام "vectorization" للإشارة إلى استخدام تعليمات SIMD CPU التي تحسب عبر مدخلات متعددة بشكل متزامن ، باستثناء أن كلاهما يستخدم استعارة مماثلة: إنهما مثل نظرائهما "القياسيين" ، لكنهما يؤديان الحساب على قيم إدخال متعددة بدعوة واحدة.

مع numpy.vectorize() ، لا يوجد عادةً الكثير من مزايا السرعة على حلقة Python for الصريحة. الهدف الرئيسي منها هو تحويل دالة Python إلى ufunc ، والتي تنفذ جميع دلالات البث وبالتالي تتعامل مع أي حجم من المدخلات. لا تزال وظيفة Python التي يتم "تحويلها" تستغرق معظم الوقت ، بالإضافة إلى تحويل القيمة الأولية لكل عنصر إلى كائن Python لتمريرها إلى الوظيفة. لا تتوقع أن يكون np.vectorize(lambda x, y: x + y) بنفس سرعة ufunc np.add ، وهو C في كل من الحلقة ومحتويات الحلقة.

شكرا لك على شرحك المفصل. ولكن لكي أكون واضحًا ، اسمحوا لي أن آخذ مثالاً.

import pandas as pd
import numpy as np
df = pd.DataFrame({'a': range(100000), 'b': range(1, 1000001)})
# method1
df.loc[:, 'c'] = df.apply(lambda x: x['a'] + x['b'], axis=1)
# method2 
df.loc[:, 'c'] = np.vectorize(lambda x, y: x + y)(df['a'], df['b'])
# method3
df.loc[:, 'c'] = np.add(df['a'], df['b'])

لذلك مع شرحك ، أعتقد

طريقة | حلقة في C | محتوى الحلقة في C | استخدم SIMD
- | - | - | -
1 | × | × | ×
2 | √ | × | ×
3 | √ | √ | √

حق؟

np.add أسرع من np.vectorize(lambda x, y: x + y) لأنه يتجنب تحويل مضاعفات C إلى كائنات Python ودالة استدعاء دالة Python. من المحتمل أنه يستخدم أيضًا تعليمات SIMD ، اعتمادًا على ما إذا كان لديك امتدادات AVX2 أم لا ، ولكن هذا ليس السبب في أنه أسرع.

np.add أسرع من np.vectorize(lambda x, y: x + y) لأنه يتجنب تحويل مضاعفات C إلى كائنات Python ودالة استدعاء دالة Python. من المحتمل أيضًا أنه يستخدم تعليمات SIMD ، اعتمادًا على ما إذا كان لديك امتدادات AVX2 أم لا ، ولكن هذا ليس السبب في أنه أسرع.

فهمت. شكر.

يمكنك استخدام numba vectorize لإنتاج ufuncs تعمل بالتوازي بدون مصاريف بايثون:

https://numba.pydata.org/numba-doc/latest/user/vectorize.html

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات