.__skip_array_function__
للسماح بتخطي إرسال __array_function__
. (https://github.com/numpy/numpy/pull/13389)numpy/core/overrides.py
في C للسرعة (https://github.com/numpy/numpy/issues/12028):get_overloaded_types_and_args
array_function_implementation_or_override
ndarray.__array_function__
؟array_function_dispatch
؟numpy.core
np.core.defchararray
(# 12154)np.einsum
و np.block
(https://github.com/numpy/numpy/pull/12163)numpy.lib
numpy.fft
/ numpy.linalg
(https://github.com/numpy/numpy/pull/12117)arange?
] (https://github.com/numpy/numpy/issues/12379)ndarray.__repr__
على __array_function__
(https://github.com/numpy/numpy/pull/12212)stacklevel
بمقدار 1 للوظائف المغلفة ، لذلك تشير عمليات التتبع إلى المكان الصحيح (gh-13329)قد يكون من الجيد دمج "تزيين جميع وظائف NumPy العامة معarray_function_dispatch" لبعض الوظائف البارزة وطلب المستهلكين من البروتوكول لتجربته
بمجرد أن ندمج https://github.com/numpy/numpy/pull/12099 ، لديّ علاقات عامة أخرى جاهزة من شأنها إضافة ديكورات إرسال لمعظم numpy.core
. سيكون من السهل جدًا إنهاء الأشياء - استغرق هذا الأمر أقل من ساعة لتجميعه.
سم مكعب @ اريك-يزرmrocklinmhvkhameerabbasi
راجع https://github.com/shoyer/numpy/tree/array-function-easy-impl لفرعي الذي ينفذ جميع التجاوزات "السهلة" على الوظائف باستخدام أغلفة Python. الأجزاء المتبقية هي np.block
، np.einsum
وحفنة من وظائف الدالات المتعددة مكتوبة بالكامل في C (على سبيل المثال ، np.concatenate
). سأقسم هذا إلى مجموعة من العلاقات العامة بمجرد أن ننتهي من # 12099.
لاحظ أنني لم أكتب اختبارات للتجاوزات على كل وظيفة على حدة. أود إضافة بعض اختبارات التكامل عندما ننتهي (على سبيل المثال ، مصفوفة البط التي تسجل جميع العمليات المطبقة) ، لكنني لا أعتقد أنه سيكون من المفيد كتابة اختبارات إرسال لكل وظيفة على حدة. يجب أن تكتشف الشيكات في # 12099 الأخطاء الأكثر شيوعًا على المرسلين ، ويجب تنفيذ كل سطر من التعليمات البرمجية في وظائف المرسل من خلال الاختبارات الحالية.
shoyer - في الاختبارات ، أوافق على أنه ليس من المفيد بشكل خاص كتابة الاختبارات لكل اختبار ؛ بدلاً من ذلك ، داخل numpy ، قد يكون من المنطقي البدء في استخدام التجاوزات بسرعة نسبيًا في MaskedArray
.
يبدو mhvk جيدًا بالنسبة لي ، على الرغم من أنني سأسمح لشخص آخر يستخدم / يعرف MaskedArray بأخذ زمام المبادرة في ذلك.
راجع https://github.com/numpy/numpy/pull/12115 و https://github.com/numpy/numpy/pull/12116 و # 12119 و https://github.com/numpy/numpy/pull/ 12117 لـ PRs الذين يطبقون دعم __array_function__
للوظائف المحددة في Python.
shoyer - عند رؤية بعض التطبيقات ، لدي
reshape
، قدمت الوظيفة الأصلية بالفعل طريقة لتجاوزها ، من خلال تحديد طريقة reshape
. نحن نستبعد ذلك فعليًا لأي فئة تحدد __array_function__
.np.median
، فإن الاستخدام الدقيق لـ np.asanyarray
و ufuncs يضمن أن الفئات الفرعية يمكنها استخدامها بالفعل. ولكن لم يعد من الممكن الوصول إلى هذه الوظيفة مباشرة.أعتقد بشكل عام أن هذين الأمرين هما على الأرجح فوائد ، نظرًا لأننا نبسط الواجهة ويمكننا جعل عمليات التنفيذ محسّنة لـ ndarray
- على الرغم من أن الأخير يشير إلى أن ndarray.__array_function__
يجب أن يتولى قوائم التحويل ، وما إلى ذلك ، إلى ndarray
، بحيث يمكن للتطبيقات تخطي هذا الجزء). ومع ذلك ، اعتقدت أنني سألاحظ ذلك لأنه يجعلني أشعر بالرهبة من تنفيذ هذا مقابل Quantity
أكثر قليلاً مما كنت أعتقد - من حيث مقدار العمل والضربة المحتملة في الأداء.
على الرغم من أن الأخير يقترح أن ndarray .__ يجب أن تتولى الدالة array_function__ تحويل القوائم ، وما إلى ذلك ، إلى ndarray ، بحيث يمكن للتطبيقات تخطي هذا الجزء).
لست متأكدًا من أنني أتابع هنا.
نحن بالفعل نستنكر الطريقة القديمة لإلغاء الوظائف مثل reshape
و mean
، على الرغم من أن الطريقة القديمة لا تزال تدعم عمليات التنفيذ غير المكتملة لواجهة برمجة تطبيقات NumPy.
لست متأكدًا من أنني أتابع هنا.
أعتقد أن المشكلة تكمن في أننا إذا طبقنا __array_function__
لوظيفة واحدة ، فإن الآليات السابقة تنكسر تمامًا ولا توجد طريقة لتجاوز الفشل. ولهذا أقترح إعادة النظر في اقتراحي NotImplementedButCoercible
.
hameerabbasi - نعم ، هذه هي المشكلة. على الرغم من أننا بحاجة إلى توخي الحذر هنا في مدى سهولة الاعتماد على حلول الشريط اللاصق التي نفضل التخلص منها حقًا ... (ولهذا السبب كتبت أعلاه أن "مشاكلي" قد تكون في الواقع فوائد ...) . ربما توجد حالة للمحاولة كما هي في 1.16 ثم اتخاذ قرار بشأن التجربة الفعلية فيما إذا كنا نريد توفير احتياطي لـ "تجاهل __array_function__
الخاص بي لهذه الحالة".
إعادة: تصميم المرسل: تستند تفضيلاتي على النمط إلى اعتبارات الذاكرة / وقت الاستيراد والإسهاب. بكل بساطة ، قم بدمج المرسلين حيث من المحتمل أن يظل التوقيع كما هو. بهذه الطريقة ، نقوم بإنشاء أقل عدد من العناصر وستكون نتائج ذاكرة التخزين المؤقت أعلى أيضًا.
ومع ذلك ، فأنا لا أعارض أسلوب لامدا كثيرًا.
لقد ظهر الآن أسلوب كتابة وظائف المرسل في عدد قليل من العلاقات العامة. سيكون من الجيد اتخاذ خيار ثابت عبر NumPy.
لدينا بعض الخيارات:
الخيار 1 : اكتب مرسل منفصل لكل وظيفة ، على سبيل المثال ،
def _sin_dispatcher(a):
return (a,)
@array_function_dispatch(_sin_dispatcher)
def sin(a):
...
def _cos_dispatcher(a):
return (a,)
@array_function_dispatch(_cos_dispatcher)
def cos(a):
...
مزايا:
sin(x=1)
-> TypeError: _sin_dispatcher() got an unexpected keyword argument 'x'
.سلبيات:
الخيار 2 : إعادة استخدام وظائف المرسل داخل وحدة نمطية ، على سبيل المثال ،
def _unary_dispatcher(a):
return (a,)
@array_function_dispatch(_unary_dispatcher)
def sin(a):
...
@array_function_dispatch(_unary_dispatcher)
def cos(a):
...
مزايا:
سلبيات:
sin(x=1)
-> TypeError: _unary_dispatcher() got an unexpected keyword argument 'x'
الخيار 3 : استخدم وظائف lambda
عندما يكون تعريف المرسل مناسبًا لسطر واحد ، على سبيل المثال ،
# inline style (shorter)
@array_function_dispatch(lambda a: (a,))
def sin(a):
...
@array_function_dispatch(lambda a, n=None, axis=None, norm=None: (a,))
def fft(a, n=None, axis=-1, norm=None):
...
# multiline style (more readable?)
@array_function_dispatch(
lambda a: (a,)
)
def sin(a):
...
@array_function_dispatch(
lambda a, n=None, axis=None, norm=None: (a,)
)
def fft(a, n=None, axis=-1, norm=None):
...
مزايا:
سلبيات:
TypeError: <lambda>() got an unexpected keyword argument 'x'
)shoyer : تم التعديل لإضافة تباعد PEP8 المكون من سطرين لجعل جانب "سطور الكود" أكثر واقعية
لاحظ أنه يمكن إصلاح مشكلات رسالة الخطأ عن طريق إعادة بناء كائن التعليمات البرمجية ، على الرغم من أن ذلك سيأتي بتكلفة وقت الاستيراد. ربما يستحق التحقيق ، وكسر تونةnschloe لمقارنة بعض الخيارات.
نعم ، يمكن أيضًا استخدام وحدة التزيين لتوليد تعريف الوظيفة (تستخدم طريقة مختلفة قليلاً لإنشاء الكود ، تشبه إلى حدٍ ما الاسمات المزدوجة من حيث أنها تستخدم exec()
).
طالما لم يتم حل الخطأ ، أعتقد أننا بحاجة إلى الالتزام بالخيارات مع المرسل الذي له اسم واضح. أود قليلاً أن أقوم بتجميع المرسلين معًا (2) لأسباب تتعلق بالذاكرة ، على الرغم من أنني سأضع رسالة الخطأ في الاعتبار كثيرًا ، لذلك أقترح استدعاء المرسل شيئًا مثل _dispatch_on_x
.
على الرغم من أنه إذا تمكنا من تغيير الخطأ ، فإن الأشياء تتغير. على سبيل المثال ، قد يكون الأمر بسيطًا مثل التقاط الاستثناءات ، واستبدال <lambda>
باسم الوظيفة في نص الاستثناء ، ثم إعادة الزيادة. (أم أن هذه السلسلة من الأشياء هذه الأيام؟)
أوافق على أن رسالة الخطأ يجب أن تكون واضحة ، ومن الأفضل ألا تتغير على الإطلاق.
حسنًا ، أعتقد في الوقت الحالي أنه من الأفضل تأجيل استخدام lambda
، ما لم نحصل على نوع من إنشاء الكود.
يضيف https://github.com/numpy/numpy/pull/12175 مسودة لما يمكن أن تبدو عليه تجاوزات وظائف المصفوفات المتعددة (مكتوبة بلغة C) إذا اتبعنا نهج غلاف Python.
mattip أين وصلنا عند تنفيذ matmul
كـ ufunc؟ بمجرد الانتهاء من كل هذه التجاوزات __array_function__
، أعتقد أن هذا هو آخر شيء نحتاجه لجعل واجهة برمجة تطبيقات NumPy العامة قابلة للتحميل بشكل زائد. سيكون من الجيد أن يكون كل شيء جاهزًا لـ NumPy 1.16!
يحقق PR # 11175 ، الذي ينفذ NEP 20 ، تقدمًا بطيئًا. وهو مانع لـ PR # 11133 ، والذي يحتوي على كود حلقة matmul. لا يزال هذا الشخص بحاجة إلى التحديث ثم التحقق من ذلك عبر معايير أن الكود الجديد ليس أبطأ من الرمز القديم.
لدي أربعة علاقات عامة للمراجعة والتي يجب أن تكمل المجموعة الكاملة من التجاوزات. سيكون موضع تقدير المراجعات / التوقيعات / الدمج النهائية حتى نتمكن من البدء في اختبار __array_function__
بشكل جدي! https://github.com/numpy/numpy/pull/12154 ، https://github.com/numpy/numpy/pull/12163 ، https://github.com/numpy/numpy/pull/12119 ، https: //github.com/numpy/numpy/pull/12175
تسببت إضافة التخطي إلى np.core
فشل بعض اختبارات الباندا (https://github.com/pandas-dev/pandas/issues/23172). لسنا متأكدين تمامًا مما يحدث حتى الآن ، لكن يجب علينا بالتأكيد اكتشاف ذلك قبل الإفراج عنه.
راجع https://github.com/numpy/numpy/issues/12225 للحصول على أفضل تخمينات عن سبب تسبب هذا في فشل الاختبار في dask / pandas.
بعض المعايير القياسية لأوقات الاستيراد (على جهاز macbook Pro الخاص بي المزود بمحرك أقراص الحالة الصلبة):
decorator.decorate
(# 12226): 183.694 مللي ثانيةالبرنامج النصي المعياري الخاص بي
import numpy as np
import subprocess
times = []
for _ in range(100):
result = subprocess.run("python -X importtime -c 'import numpy'",
shell=True, capture_output=True)
last_line = result.stderr.rstrip().split(b'\n')[-1]
time = float(last_line.decode('ascii')[-15:-7].strip().rstrip())
times.append(time)
print(np.median(times) / 1e3)
أي فكرة عن استخدام الذاكرة (قبل / بعد)؟ هذا مفيد أيضًا ، خاصة لتطبيقات إنترنت الأشياء.
هل تعرف كيف تقيس بشكل موثوق استخدام الذاكرة لوحدة ما؟
يوم السبت 20 أكتوبر 2018 الساعة 6:56 صباحًا Hameer Abbasi [email protected]
كتب:
أي فكرة عن استخدام الذاكرة (قبل / بعد)؟ هذا نوع من المفيد مثل
حسنًا ، خاصة لتطبيقات إنترنت الأشياء.-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/12028#issuecomment-431584123 ، أو كتم الصوت
الخيط
https://github.com/notifications/unsubscribe-auth/ABKS1k_IkrJ2YmYReaDrnkNvcH2X0-ZCks5umyuogaJpZM4W3kSC
.
أعتقد أن كتابة نص يحتوي على import numpy as np
، إضافة بيان النوم وذاكرة عملية التتبع يجب أن يكون جيدًا بما فيه الكفاية. https://superuser.com/questions/581108/how-can-i-track-and-log-cpu-and-memory-usage-on-a-mac
أي مطوري نواة آخرين يريدون إلقاء نظرة سريعة (حقًا ، إنه يتضمن وظيفتين فقط!) على https://github.com/numpy/numpy/pull/12163؟ إنها آخر العلاقات العامة التي تضيف array_function_dispatch
إلى وظائف numpy الداخلية.
كمرجع ، إليك اختلاف الأداء الذي أراه عند تعطيل __array_function__
:
before after ratio
[45718fd7] [4e5aa2cd]
<master> <disable-array-function>
+ 72.5±2ms 132±20ms 1.82 bench_io.LoadtxtCSVdtypes.time_loadtxt_dtypes_csv('complex128', 10000)
- 44.9±2μs 40.8±0.6μs 0.91 bench_ma.Concatenate.time_it('ndarray', 2)
- 15.3±0.3μs 13.3±0.7μs 0.87 bench_core.CountNonzero.time_count_nonzero_multi_axis(2, 100, <type 'object'>)
- 38.4±1μs 32.7±2μs 0.85 bench_linalg.Linalg.time_op('norm', 'longfloat')
- 68.7±3μs 56.5±3μs 0.82 bench_linalg.Linalg.time_op('norm', 'complex256')
- 80.6±4μs 65.9±1μs 0.82 bench_function_base.Median.time_even
- 82.4±2μs 66.8±3μs 0.81 bench_shape_base.Block.time_no_lists(100)
- 73.5±3μs 59.3±3μs 0.81 bench_function_base.Median.time_even_inplace
- 15.2±0.3μs 12.2±0.6μs 0.80 bench_core.CountNonzero.time_count_nonzero_multi_axis(3, 100, <type 'str'>)
- 2.20±0.1ms 1.76±0.04ms 0.80 bench_shape_base.Block2D.time_block2d((1024, 1024), 'uint64', (4, 4))
- 388±20μs 310±10μs 0.80 bench_lib.Pad.time_pad((10, 10, 10), 3, 'linear_ramp')
- 659±20μs 524±20μs 0.80 bench_linalg.Linalg.time_op('det', 'float32')
- 22.9±0.7μs 18.2±0.8μs 0.79 bench_function_base.Where.time_1
- 980±50μs 775±20μs 0.79 bench_shape_base.Block2D.time_block2d((1024, 1024), 'uint32', (4, 4))
- 36.6±1μs 29.0±1μs 0.79 bench_ma.Concatenate.time_it('unmasked', 2)
- 16.4±0.7μs 12.9±0.6μs 0.79 bench_core.CountNonzero.time_count_nonzero_axis(3, 100, <type 'str'>)
- 16.4±0.5μs 12.9±0.4μs 0.79 bench_core.CountNonzero.time_count_nonzero_axis(2, 100, <type 'object'>)
- 141±5μs 110±4μs 0.78 bench_lib.Pad.time_pad((10, 100), (0, 5), 'linear_ramp')
- 18.0±0.6μs 14.1±0.6μs 0.78 bench_core.CountNonzero.time_count_nonzero_axis(3, 100, <type 'object'>)
- 11.9±0.6μs 9.28±0.5μs 0.78 bench_core.CountNonzero.time_count_nonzero_axis(1, 100, <type 'int'>)
- 54.6±3μs 42.4±2μs 0.78 bench_function_base.Median.time_odd_small
- 317±10μs 246±7μs 0.78 bench_lib.Pad.time_pad((10, 10, 10), 1, 'linear_ramp')
- 13.8±0.5μs 10.7±0.7μs 0.77 bench_reduce.MinMax.time_min(<type 'numpy.float64'>)
- 73.3±6μs 56.6±4μs 0.77 bench_lib.Pad.time_pad((1000,), (0, 5), 'mean')
- 14.7±0.7μs 11.4±0.3μs 0.77 bench_core.CountNonzero.time_count_nonzero_axis(2, 100, <type 'str'>)
- 21.5±2μs 16.5±0.6μs 0.77 bench_reduce.MinMax.time_min(<type 'numpy.int64'>)
- 117±4μs 89.2±3μs 0.76 bench_lib.Pad.time_pad((1000,), 3, 'linear_ramp')
- 43.7±1μs 33.4±1μs 0.76 bench_linalg.Linalg.time_op('norm', 'complex128')
- 12.6±0.6μs 9.55±0.2μs 0.76 bench_core.CountNonzero.time_count_nonzero_multi_axis(2, 100, <type 'int'>)
- 636±20μs 482±20μs 0.76 bench_ma.MA.time_masked_array_l100
- 86.6±4μs 65.6±4μs 0.76 bench_lib.Pad.time_pad((1000,), (0, 5), 'linear_ramp')
- 120±4μs 90.4±2μs 0.75 bench_lib.Pad.time_pad((1000,), 1, 'linear_ramp')
- 160±5μs 119±8μs 0.74 bench_ma.Concatenate.time_it('ndarray+masked', 100)
- 14.4±0.6μs 10.7±0.3μs 0.74 bench_core.CountNonzero.time_count_nonzero_multi_axis(1, 100, <type 'str'>)
- 15.7±0.4μs 11.7±0.6μs 0.74 bench_core.CountNonzero.time_count_nonzero_multi_axis(2, 100, <type 'str'>)
- 21.8±2μs 16.1±0.7μs 0.74 bench_reduce.MinMax.time_max(<type 'numpy.int64'>)
- 11.9±0.6μs 8.79±0.3μs 0.74 bench_core.CountNonzero.time_count_nonzero_axis(2, 100, <type 'bool'>)
- 53.8±3μs 39.4±2μs 0.73 bench_function_base.Median.time_even_small
- 106±20μs 76.7±4μs 0.73 bench_function_base.Select.time_select
- 168±10μs 122±4μs 0.72 bench_shape_base.Block2D.time_block2d((512, 512), 'uint32', (2, 2))
- 12.5±0.5μs 8.96±0.4μs 0.72 bench_core.CountNonzero.time_count_nonzero_multi_axis(1, 100, <type 'int'>)
- 162±10μs 115±5μs 0.71 bench_function_base.Percentile.time_percentile
- 12.9±1μs 9.12±0.4μs 0.71 bench_random.Random.time_rng('normal')
- 9.71±0.4μs 6.88±0.3μs 0.71 bench_core.CorrConv.time_convolve(1000, 10, 'full')
- 15.1±0.8μs 10.7±0.4μs 0.71 bench_reduce.MinMax.time_max(<type 'numpy.float64'>)
- 153±9μs 108±7μs 0.71 bench_shape_base.Block2D.time_block2d((1024, 1024), 'uint8', (2, 2))
- 109±5μs 76.9±5μs 0.71 bench_ma.Concatenate.time_it('ndarray+masked', 2)
- 34.3±1μs 24.2±0.6μs 0.71 bench_linalg.Linalg.time_op('norm', 'complex64')
- 9.80±0.2μs 6.84±0.5μs 0.70 bench_core.CorrConv.time_convolve(1000, 10, 'same')
- 27.4±6μs 19.1±2μs 0.70 bench_core.CountNonzero.time_count_nonzero_axis(1, 10000, <type 'bool'>)
- 9.35±0.4μs 6.50±0.3μs 0.70 bench_core.CorrConv.time_convolve(50, 100, 'full')
- 65.2±4μs 45.2±1μs 0.69 bench_shape_base.Block.time_block_simple_row_wise(100)
- 12.9±1μs 8.89±0.3μs 0.69 bench_core.CountNonzero.time_count_nonzero_axis(3, 100, <type 'bool'>)
- 19.6±3μs 13.5±0.4μs 0.69 bench_core.CountNonzero.time_count_nonzero_multi_axis(3, 100, <type 'object'>)
- 75.6±2μs 52.1±3μs 0.69 bench_lib.Pad.time_pad((10, 10, 10), (0, 5), 'reflect')
- 12.4±1μs 8.51±0.4μs 0.69 bench_core.CountNonzero.time_count_nonzero_multi_axis(3, 100, <type 'bool'>)
- 172±30μs 117±4μs 0.68 bench_ma.Concatenate.time_it('unmasked+masked', 100)
- 23.1±0.5μs 15.8±0.9μs 0.68 bench_linalg.Linalg.time_op('norm', 'int16')
- 8.18±0.9μs 5.57±0.1μs 0.68 bench_core.CorrConv.time_correlate(1000, 10, 'full')
- 153±5μs 103±3μs 0.68 bench_function_base.Percentile.time_quartile
- 758±100μs 512±20μs 0.68 bench_linalg.Linalg.time_op('det', 'int16')
- 55.4±6μs 37.4±1μs 0.68 bench_ma.Concatenate.time_it('masked', 2)
- 234±30μs 157±5μs 0.67 bench_shape_base.Block.time_nested(100)
- 103±4μs 69.3±3μs 0.67 bench_linalg.Eindot.time_dot_d_dot_b_c
- 19.2±0.4μs 12.9±0.6μs 0.67 bench_core.Core.time_tril_l10x10
- 122±7μs 81.7±4μs 0.67 bench_lib.Pad.time_pad((10, 10, 10), 3, 'edge')
- 22.9±1μs 15.3±0.5μs 0.67 bench_linalg.Linalg.time_op('norm', 'int32')
- 16.6±2μs 11.0±0.3μs 0.66 bench_core.CountNonzero.time_count_nonzero_multi_axis(1, 100, <type 'object'>)
- 9.98±0.3μs 6.58±0.1μs 0.66 bench_core.CorrConv.time_convolve(1000, 10, 'valid')
- 118±6μs 77.9±4μs 0.66 bench_shape_base.Block2D.time_block2d((512, 512), 'uint16', (2, 2))
- 212±50μs 140±8μs 0.66 bench_lib.Pad.time_pad((10, 10, 10), (0, 5), 'mean')
- 21.9±0.7μs 14.4±0.5μs 0.66 bench_linalg.Linalg.time_op('norm', 'int64')
- 131±5μs 85.9±5μs 0.65 bench_lib.Pad.time_pad((10, 10, 10), 3, 'constant')
- 56.8±2μs 37.0±3μs 0.65 bench_lib.Pad.time_pad((1000,), (0, 5), 'constant')
- 58.9±3μs 38.1±1μs 0.65 bench_lib.Pad.time_pad((10, 100), (0, 5), 'reflect')
- 72.1±2μs 46.5±3μs 0.64 bench_lib.Pad.time_pad((10, 100), (0, 5), 'constant')
- 8.66±0.3μs 5.58±0.2μs 0.64 bench_core.CorrConv.time_correlate(50, 100, 'full')
- 300±30μs 193±10μs 0.64 bench_shape_base.Block2D.time_block2d((1024, 1024), 'uint8', (4, 4))
- 15.9±5μs 10.2±0.3μs 0.64 bench_core.CountNonzero.time_count_nonzero_axis(3, 100, <type 'int'>)
- 13.7±0.5μs 8.80±0.1μs 0.64 bench_random.Random.time_rng('uniform')
- 8.60±0.5μs 5.50±0.2μs 0.64 bench_core.CorrConv.time_correlate(1000, 10, 'same')
- 44.7±2μs 28.5±0.7μs 0.64 bench_lib.Pad.time_pad((1000,), 1, 'reflect')
- 72.7±3μs 46.2±2μs 0.64 bench_lib.Pad.time_pad((10, 10, 10), 3, 'wrap')
- 567±50μs 360±40μs 0.63 bench_shape_base.Block2D.time_block2d((512, 512), 'uint64', (2, 2))
- 58.0±3μs 36.7±2μs 0.63 bench_lib.Pad.time_pad((10, 100), 3, 'reflect')
- 219±30μs 138±7μs 0.63 bench_lib.Pad.time_pad((10, 100), 1, 'mean')
- 261±60μs 164±10μs 0.63 bench_lib.Pad.time_pad((10, 100), 1, 'linear_ramp')
- 825±100μs 519±30μs 0.63 bench_shape_base.Block2D.time_block2d((512, 512), 'uint64', (4, 4))
- 121±5μs 75.7±2μs 0.63 bench_lib.Pad.time_pad((10, 10, 10), 1, 'constant')
- 8.16±0.2μs 5.08±0.4μs 0.62 bench_core.CorrConv.time_convolve(50, 100, 'same')
- 66.6±3μs 41.3±2μs 0.62 bench_lib.Pad.time_pad((1000,), 3, 'constant')
- 53.1±3μs 32.9±0.8μs 0.62 bench_lib.Pad.time_pad((10, 100), 3, 'wrap')
- 285±60μs 177±10μs 0.62 bench_lib.Pad.time_pad((10, 10, 10), (0, 5), 'linear_ramp')
- 8.30±0.9μs 5.14±0.1μs 0.62 bench_core.CorrConv.time_correlate(1000, 10, 'valid')
- 115±3μs 71.2±3μs 0.62 bench_shape_base.Block2D.time_block2d((256, 256), 'uint64', (2, 2))
- 19.1±0.5μs 11.8±0.6μs 0.62 bench_linalg.Linalg.time_op('norm', 'float64')
- 95.3±5μs 58.6±2μs 0.62 bench_lib.Pad.time_pad((10, 100), 1, 'constant')
- 44.6±1μs 27.2±0.9μs 0.61 bench_lib.Pad.time_pad((1000,), (0, 5), 'edge')
- 447±20μs 270±10μs 0.61 bench_shape_base.Block2D.time_block2d((1024, 1024), 'uint16', (4, 4))
- 53.9±2μs 32.6±2μs 0.60 bench_lib.Pad.time_pad((10, 100), 1, 'wrap')
- 11.6±1μs 6.97±0.4μs 0.60 bench_reduce.MinMax.time_max(<type 'numpy.float32'>)
- 95.9±5μs 57.7±2μs 0.60 bench_lib.Pad.time_pad((10, 100), 3, 'constant')
- 47.2±2μs 28.2±2μs 0.60 bench_lib.Pad.time_pad((1000,), (0, 5), 'reflect')
- 5.51±0.2μs 3.27±0.07μs 0.59 bench_core.CountNonzero.time_count_nonzero(3, 100, <type 'object'>)
- 74.3±3μs 44.0±2μs 0.59 bench_lib.Pad.time_pad((10, 10, 10), (0, 5), 'wrap')
- 76.2±3μs 45.0±0.8μs 0.59 bench_lib.Pad.time_pad((10, 10, 10), 1, 'reflect')
- 57.1±1μs 33.5±2μs 0.59 bench_lib.Pad.time_pad((10, 100), (0, 5), 'wrap')
- 52.0±2μs 30.4±1μs 0.58 bench_lib.Pad.time_pad((1000,), 1, 'edge')
- 42.6±2μs 24.9±0.9μs 0.58 bench_lib.Pad.time_pad((1000,), 3, 'wrap')
- 15.0±3μs 8.73±0.3μs 0.58 bench_core.CountNonzero.time_count_nonzero_multi_axis(1, 100, <type 'bool'>)
- 16.0±3μs 9.29±0.3μs 0.58 bench_core.CountNonzero.time_count_nonzero_multi_axis(3, 100, <type 'int'>)
- 53.1±1μs 30.9±2μs 0.58 bench_lib.Pad.time_pad((1000,), 3, 'edge')
- 88.0±8μs 51.1±3μs 0.58 bench_lib.Pad.time_pad((10, 10, 10), 3, 'reflect')
- 44.6±2μs 25.9±1μs 0.58 bench_lib.Pad.time_pad((1000,), (0, 5), 'wrap')
- 90.3±5μs 51.9±1μs 0.57 bench_shape_base.Block2D.time_block2d((512, 512), 'uint8', (2, 2))
- 15.6±0.5μs 8.93±0.3μs 0.57 bench_linalg.Linalg.time_op('norm', 'float32')
- 102±6μs 58.3±0.9μs 0.57 bench_lib.Pad.time_pad((10, 10, 10), 1, 'edge')
- 80.1±4μs 45.6±3μs 0.57 bench_lib.Pad.time_pad((10, 100), 3, 'edge')
- 44.2±2μs 24.9±1μs 0.56 bench_lib.Pad.time_pad((1000,), 1, 'wrap')
- 71.6±8μs 39.5±1μs 0.55 bench_lib.Pad.time_pad((10, 10, 10), 1, 'wrap')
- 81.7±10μs 44.8±2μs 0.55 bench_lib.Pad.time_pad((10, 100), 1, 'edge')
- 420±90μs 230±10μs 0.55 bench_shape_base.Block.time_3d(10, 'block')
- 114±20μs 62.3±2μs 0.55 bench_lib.Pad.time_pad((10, 10, 10), (0, 5), 'constant')
- 5.76±0.1μs 3.13±0.08μs 0.54 bench_core.CorrConv.time_convolve(50, 10, 'same')
- 5.30±0.1μs 2.84±0.08μs 0.54 bench_core.CorrConv.time_correlate(50, 100, 'valid')
- 92.5±4μs 49.3±1μs 0.53 bench_shape_base.Block2D.time_block2d((256, 256), 'uint32', (2, 2))
- 13.5±3μs 7.07±0.2μs 0.52 bench_reduce.MinMax.time_min(<type 'numpy.float32'>)
- 7.66±1μs 3.88±0.2μs 0.51 bench_core.CorrConv.time_convolve(50, 100, 'valid')
- 29.0±3μs 14.5±0.8μs 0.50 bench_shape_base.Block.time_no_lists(10)
- 6.62±0.3μs 3.30±0.2μs 0.50 bench_core.CorrConv.time_convolve(1000, 1000, 'valid')
- 74.2±7μs 36.2±0.9μs 0.49 bench_shape_base.Block2D.time_block2d((256, 256), 'uint16', (2, 2))
- 5.55±0.3μs 2.70±0.2μs 0.49 bench_core.CorrConv.time_convolve(50, 10, 'valid')
- 73.9±20μs 35.8±2μs 0.48 bench_lib.Pad.time_pad((10, 100), 1, 'reflect')
- 224±20μs 107±7μs 0.48 bench_shape_base.Block2D.time_block2d((256, 256), 'uint64', (4, 4))
- 3.87±0.1μs 1.83±0.06μs 0.47 bench_core.CountNonzero.time_count_nonzero(2, 100, <type 'str'>)
- 109±30μs 51.5±3μs 0.47 bench_lib.Pad.time_pad((10, 10, 10), (0, 5), 'edge')
- 240±20μs 112±4μs 0.47 bench_shape_base.Block2D.time_block2d((512, 512), 'uint16', (4, 4))
- 337±40μs 158±7μs 0.47 bench_shape_base.Block2D.time_block2d((512, 512), 'uint32', (4, 4))
- 188±8μs 88.0±2μs 0.47 bench_shape_base.Block2D.time_block2d((512, 512), 'uint8', (4, 4))
- 4.39±0.2μs 2.04±0.09μs 0.47 bench_core.CountNonzero.time_count_nonzero(3, 10000, <type 'bool'>)
- 73.2±4μs 33.9±0.5μs 0.46 bench_shape_base.Block2D.time_block2d((128, 128), 'uint64', (2, 2))
- 5.48±1μs 2.44±0.1μs 0.45 bench_core.CountNonzero.time_count_nonzero(2, 100, <type 'object'>)
- 4.46±0.1μs 1.97±0.08μs 0.44 bench_core.CorrConv.time_correlate(50, 10, 'full')
- 30.4±9μs 13.3±0.3μs 0.44 bench_shape_base.Block.time_no_lists(1)
- 7.05±0.2μs 3.05±0.06μs 0.43 bench_reduce.SmallReduction.time_small
- 7.35±1μs 3.12±0.2μs 0.42 bench_core.CorrConv.time_convolve(50, 10, 'full')
- 4.36±0.1μs 1.84±0.07μs 0.42 bench_core.CorrConv.time_correlate(50, 10, 'same')
- 3.51±0.2μs 1.46±0.05μs 0.42 bench_core.CountNonzero.time_count_nonzero(1, 100, <type 'object'>)
- 4.03±0.05μs 1.66±0.1μs 0.41 bench_core.CorrConv.time_correlate(1000, 1000, 'valid')
- 199±10μs 80.1±3μs 0.40 bench_shape_base.Block2D.time_block2d((256, 256), 'uint32', (4, 4))
- 3.98±0.2μs 1.60±0.08μs 0.40 bench_core.CountNonzero.time_count_nonzero(2, 10000, <type 'bool'>)
- 61.8±2μs 24.8±1μs 0.40 bench_shape_base.Block2D.time_block2d((256, 256), 'uint8', (2, 2))
- 4.13±0.1μs 1.62±0.05μs 0.39 bench_core.CorrConv.time_correlate(50, 10, 'valid')
- 61.6±2μs 23.9±1μs 0.39 bench_shape_base.Block2D.time_block2d((128, 128), 'uint32', (2, 2))
- 184±10μs 70.5±3μs 0.38 bench_shape_base.Block2D.time_block2d((256, 256), 'uint16', (4, 4))
- 56.1±4μs 21.0±0.9μs 0.38 bench_shape_base.Block2D.time_block2d((64, 64), 'uint64', (2, 2))
- 40.0±2μs 15.0±0.6μs 0.37 bench_shape_base.Block.time_block_simple_column_wise(10)
- 121±2μs 45.1±2μs 0.37 bench_shape_base.Block.time_nested(1)
- 179±4μs 66.1±4μs 0.37 bench_shape_base.Block2D.time_block2d((128, 128), 'uint64', (4, 4))
- 59.8±2μs 22.0±1μs 0.37 bench_shape_base.Block2D.time_block2d((128, 128), 'uint16', (2, 2))
- 3.19±0.05μs 1.17±0.02μs 0.37 bench_core.CountNonzero.time_count_nonzero(1, 100, <type 'str'>)
- 54.0±3μs 19.7±1μs 0.37 bench_shape_base.Block2D.time_block2d((32, 32), 'uint64', (2, 2))
- 56.9±1μs 20.7±0.7μs 0.36 bench_shape_base.Block2D.time_block2d((64, 64), 'uint32', (2, 2))
- 3.14±0.1μs 1.14±0.04μs 0.36 bench_core.CountNonzero.time_count_nonzero(1, 10000, <type 'bool'>)
- 92.7±2μs 33.7±2μs 0.36 bench_shape_base.Block.time_block_complicated(1)
- 104±4μs 37.8±1μs 0.36 bench_shape_base.Block.time_block_complicated(10)
- 128±5μs 45.5±2μs 0.36 bench_shape_base.Block.time_nested(10)
- 196±100μs 69.4±3μs 0.35 bench_ma.Concatenate.time_it('unmasked+masked', 2)
- 153±5μs 53.9±2μs 0.35 bench_shape_base.Block2D.time_block2d((128, 128), 'uint16', (4, 4))
- 39.4±2μs 13.8±0.5μs 0.35 bench_shape_base.Block.time_block_simple_column_wise(1)
- 53.5±2μs 18.7±1μs 0.35 bench_shape_base.Block2D.time_block2d((32, 32), 'uint8', (2, 2))
- 55.2±2μs 19.3±0.6μs 0.35 bench_shape_base.Block2D.time_block2d((32, 32), 'uint16', (2, 2))
- 16.9±1μs 5.89±0.5μs 0.35 bench_core.Core.time_dstack_l
- 60.6±3μs 21.1±0.6μs 0.35 bench_shape_base.Block2D.time_block2d((128, 128), 'uint8', (2, 2))
- 25.5±0.2μs 8.88±0.3μs 0.35 bench_shape_base.Block.time_block_simple_row_wise(10)
- 54.6±3μs 19.0±0.6μs 0.35 bench_shape_base.Block2D.time_block2d((16, 16), 'uint64', (2, 2))
- 52.6±2μs 18.2±0.7μs 0.35 bench_shape_base.Block2D.time_block2d((16, 16), 'uint16', (2, 2))
- 6.57±2μs 2.25±0.08μs 0.34 bench_core.CountNonzero.time_count_nonzero(3, 100, <type 'str'>)
- 24.3±1μs 8.30±0.6μs 0.34 bench_shape_base.Block.time_block_simple_row_wise(1)
- 148±3μs 50.0±3μs 0.34 bench_shape_base.Block2D.time_block2d((16, 16), 'uint32', (4, 4))
- 171±8μs 57.9±4μs 0.34 bench_shape_base.Block2D.time_block2d((256, 256), 'uint8', (4, 4))
- 159±5μs 53.8±1μs 0.34 bench_shape_base.Block2D.time_block2d((64, 64), 'uint64', (4, 4))
- 171±20μs 57.7±2μs 0.34 bench_shape_base.Block2D.time_block2d((128, 128), 'uint32', (4, 4))
- 3.15±0.3μs 1.06±0.03μs 0.34 bench_core.CountNonzero.time_count_nonzero(3, 100, <type 'int'>)
- 55.7±5μs 18.7±0.2μs 0.34 bench_shape_base.Block2D.time_block2d((16, 16), 'uint8', (2, 2))
- 158±7μs 52.6±3μs 0.33 bench_shape_base.Block2D.time_block2d((128, 128), 'uint8', (4, 4))
- 153±4μs 50.7±1μs 0.33 bench_shape_base.Block2D.time_block2d((32, 32), 'uint64', (4, 4))
- 152±7μs 50.3±1μs 0.33 bench_shape_base.Block2D.time_block2d((16, 16), 'uint8', (4, 4))
- 53.6±3μs 17.7±0.4μs 0.33 bench_shape_base.Block2D.time_block2d((16, 16), 'uint32', (2, 2))
- 156±4μs 51.4±3μs 0.33 bench_shape_base.Block2D.time_block2d((64, 64), 'uint8', (4, 4))
- 148±3μs 48.2±2μs 0.33 bench_shape_base.Block2D.time_block2d((16, 16), 'uint16', (4, 4))
- 160±10μs 52.0±1μs 0.33 bench_shape_base.Block2D.time_block2d((64, 64), 'uint32', (4, 4))
- 159±8μs 51.4±3μs 0.32 bench_shape_base.Block2D.time_block2d((64, 64), 'uint16', (4, 4))
- 59.8±3μs 19.3±1μs 0.32 bench_shape_base.Block2D.time_block2d((32, 32), 'uint32', (2, 2))
- 153±4μs 49.4±2μs 0.32 bench_shape_base.Block2D.time_block2d((32, 32), 'uint32', (4, 4))
- 15.6±0.6μs 5.03±0.3μs 0.32 bench_core.Core.time_vstack_l
- 154±7μs 49.7±2μs 0.32 bench_shape_base.Block2D.time_block2d((32, 32), 'uint8', (4, 4))
- 59.6±6μs 19.1±0.8μs 0.32 bench_shape_base.Block2D.time_block2d((64, 64), 'uint8', (2, 2))
- 3.03±0.4μs 969±30ns 0.32 bench_core.CountNonzero.time_count_nonzero(2, 100, <type 'int'>)
- 120±10μs 38.4±2μs 0.32 bench_shape_base.Block.time_3d(1, 'block')
- 156±5μs 49.3±1μs 0.32 bench_shape_base.Block2D.time_block2d((16, 16), 'uint64', (4, 4))
- 164±10μs 49.3±2μs 0.30 bench_shape_base.Block2D.time_block2d((32, 32), 'uint16', (4, 4))
- 65.7±10μs 19.6±0.7μs 0.30 bench_shape_base.Block2D.time_block2d((64, 64), 'uint16', (2, 2))
- 2.82±0.08μs 732±30ns 0.26 bench_core.CountNonzero.time_count_nonzero(1, 100, <type 'int'>)
- 2.77±0.07μs 664±30ns 0.24 bench_core.CountNonzero.time_count_nonzero(2, 100, <type 'bool'>)
- 2.61±0.1μs 624±20ns 0.24 bench_core.CountNonzero.time_count_nonzero(1, 100, <type 'bool'>)
- 16.8±3μs 3.97±0.2μs 0.24 bench_core.Core.time_hstack_l
- 2.78±0.1μs 637±20ns 0.23 bench_core.CountNonzero.time_count_nonzero(3, 100, <type 'bool'>)
- 2.36±0.2μs 207±5ns 0.09 bench_overrides.ArrayFunction.time_mock_broadcast_to_numpy
- 2.68±0.1μs 221±7ns 0.08 bench_overrides.ArrayFunction.time_mock_concatenate_numpy
- 2.58±0.1μs 201±10ns 0.08 bench_overrides.ArrayFunction.time_mock_broadcast_to_duck
- 3.02±0.2μs 222±6ns 0.07 bench_overrides.ArrayFunction.time_mock_concatenate_duck
- 4.29±0.3μs 216±6ns 0.05 bench_overrides.ArrayFunction.time_mock_concatenate_mixed
- 142±20μs 213±8ns 0.00 bench_overrides.ArrayFunction.time_mock_concatenate_many
SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.
راجع أيضًا https://docs.google.com/spreadsheets/d/15-AFI_cmZqfkU6mo2p1znsQF2E52PEXpF68QqYqEar4/edit#gid = 0 للحصول على جدول بيانات.
ليس من المستغرب أن يكون الاختلاف الأكبر في الأداء للوظائف التي تستدعي وظائف numpy أخرى داخليًا عدة مرات ، على سبيل المثال ، لـ np.block()
.
shoyer - لقد شعرت استغرقته ... ربما ، يجب أن يكون لدينا حقًا تنفيذ C ، لكن في هذه الأثناء قمت بإجراء علاقات عامة مع بعض التغييرات الصغيرة التي تختفي بعض الوقت للحالة الشائعة فقط اكتب ، وللحالة التي يكون فيها النوع الوحيد هو ndarray
. انظر # 12321.
shoyer - لقد ذكرهما هنا أيضًا:
types
؟ (وليس مجرد الحجج التي توفر تجاوزًا). قد يبدو من المفيد معرفة عمليات التنفيذ. (انظر # 12327).ndarray.__array_function__
الفئات الفرعية حتى لو تجاوزت __array_function__
؟ سيكون هذا معقولًا نظرًا لمبدأ استبدال Liskov وبالنظر إلى أن الفئة الفرعية لديها بالفعل فرصة للانقاذ. قد يعني ذلك استدعاء التنفيذ بدلاً من الوظيفة العامة داخل ndarray.__array_function__
. (وشيء مشابه في __array_ufunc__
...) انظر # 12328 لتجربة مقابل __array_function__
فقط.shoyer - راجع # 12327 للحصول على تنفيذ سريع لـ (1) - إذا
و # 12328 لتجربة (2) ، لترى في الغالب كيف يبدو.
أنا +1 على كلا التعديلين هنا.
ظهر اسم وظائف المرسل في رسائل الخطأ مرة أخرى في https://github.com/numpy/numpy/pull/12789 ، حيث فوجئ شخص ما برؤية TypeError: _pad_dispatcher missing 1 required positional argument
بالإضافة إلى البدائل الموضحة أعلاه https://github.com/numpy/numpy/issues/12028#issuecomment -429377396 (نستخدم حاليًا 2) ، سأضيف خيارًا رابعًا:
الخيار 4 : اكتب مرسل منفصل لكل وظيفة ، بنفس اسم الوظيفة:
def sin(a):
return (a,)
@array_function_dispatch(sin)
def sin(a):
...
def cos(a):
return (a,)
@array_function_dispatch(cos)
def cos(a):
...
مزايا:
سلبيات:
pad
تلقى الحجج خاطئة (لكننا إجراء اختبارات للتحقق من أنها يتم الاحتفاظ بها في مزامنة).أعتقد أنه من أجل الحفاظ على عمل الكود الحالي ، يجب أن تأتي الوظيفة الفعلية _after_ المرسل.
حسنًا ، لكن يمكننا إعطائها نفس اسم المرسل. سيتم الكتابة فوق اسم المرسل.
سيكون من الرائع أن تكون قادرًا على تحديد إرسال مخصص لوظيفة مثل np.arange أو np.empty.
أعتقد أن أحد الخيارات هو إرسال NumPy على العددية وكذلك المصفوفات. هل هذا يتعارض مع السياسة الاقتصادية الجديدة؟ هل أي شيء يقطع هذا التغيير؟
للمناقشة حول np.arange
، راجع https://github.com/numpy/numpy/issues/12379.
لا أرى كيف يمكن أن يقوم np.empty()
بالإرسال - لا يوجد شيء للإرسال ، مجرد شكل ونوع. ولكن من المؤكد أن np.empty_like()
يمكنه إرسال شكل مكتوب - وهذا هو بالضبط ما يدور https://github.com/numpy/numpy/pull/13046 حول دعمه.
الخيار 4 : اكتب مرسل منفصل لكل وظيفة ، بنفس اسم الوظيفة:
أي اعتراضات على هذا الخيار؟ أعتقد أنه من المحتمل أن يكون الخيار الأكثر صداقة من منظور المستخدم.
لا أرى كيف يمكن لـ np.empty () القيام بالإرسال - لا يوجد شيء للإرسال ، مجرد شكل ونوع dtype
قد ترغب في إرسال أي من هؤلاء. على سبيل المثال ، إليك كائن شكل مخصص ، قد نرغب في إرساله بشكل مختلف.
هذا المثال ليس مفيدًا جدًا ، لكن الفكرة هي أن لدي كائنًا كسولًا يتصرف مثل الشكل ، لكنه لا يُرجع أعدادًا صحيحة ، بل يُرجع التعبيرات. على سبيل المثال ، سيكون من الجيد أن تكون قادرًا على فعل شيء مثل هذا:
class ExprShape:
def __getitem__(self, i):
return ('getitem', self, i)
def __len__(self):
return ('len', self)
numpy.empty(ExprShape())
الذي أود تجاوزه لإرجاع شيء مثل ExprArray('empty', ExprShape())
.
نعم ، من حيث المبدأ يمكننا أن ننتقل بالشكل أيضًا. سيضيف ذلك تعقيدًا إضافيًا / عبء إضافي إلى البروتوكول. هل لديك حالات استخدام لا يكفي فيها استخدام مصفوفة كقالب (مثل empty_like
مع shape
)؟
في حالات أخرى أستطيع أن أفكر في هو size
حجة ل np.random.RandomState
الأساليب، ولكن لاحظ أننا حاليا لا تدعم تلك على الإطلاق - راجع http://www.numpy.org/ neps / nep-0018-array-function-protocol.html # callable -objects-created-at-runtime
هل لديك حالات استخدام لا يكفي فيها استخدام مصفوفة كقالب (مثل فارغ _ مثل مع شكل)؟
إذا كنا نستخدم واجهة برمجة تطبيقات حالية تعتمد على NumPy ونود أن نجعلها تعمل بشفافية على خلفية مختلفة ، دون تغيير كود المصدر الحالي.
على سبيل المثال ، لنفترض أننا كنا نحاول استدعاء scipy.optimize.differential_evolution
باستخدام مصفوفات NP مثل المصفوفات ، التي تنشئ رسمًا بيانيًا للمكالمات بدلاً من تنفيذها على الفور.
يمكنك أن ترى هنا أنه سيكون من المفيد إذا تمكنا من تغيير np.full
لإنشاء مصفوفة رمزية بدلاً من مصفوفة افتراضية ، إذا كان الإدخال الذي تم تمريره إليه رمزيًا أيضًا.
إذا كنا نستخدم واجهة برمجة تطبيقات حالية تعتمد على NumPy ونود أن نجعلها تعمل بشفافية على خلفية مختلفة ، دون تغيير كود المصدر الحالي.
هذا غير ممكن بشكل عام. من المؤكد أن إنشاء مجموعة صريحة مثل np.array()
سيحتاج إلى إعادة كتابته ليكون متوافقًا مع كتابة البط.
في هذه الحالة ، يبدو تبديل energies = np.full(num_members, np.inf)
إلى energies = np.full_like(population, np.inf, shape=num_members)
تغييرًا سهلاً ومقروءًا.
هذا غير ممكن بشكل عام. إن إنشاء المصفوفة الصريحة مثل np.array () سيحتاج بالتأكيد إلى إعادة كتابته ليكون متوافقًا مع كتابة البط.
هل هناك اقتراح حول إجراء هذا النوع من التغيير أم أنك تقول إن دعم إرسال np.array
سيكون صعبًا حقًا ولذا لا يمكننا الحصول على دعم بنسبة 100٪؟
في هذه الحالة ، يبدو تبديل الطاقات = np.full (num_members، np.inf) إلى طاقات = np.full_like (السكان ، np.inf ، الشكل = num_members) تغييرًا سهلاً ويمكن قراءته.
قطعا. ولكن هناك العديد من الحالات التي لا تتحكم فيها في شفرة المصدر ، أو تريد دعم المستخدمين في استخدام الوظائف التي يعرفونها ويحبونها قدر الإمكان.
هناك طرق أخرى لتزويد المستخدمين بهذه التجربة مثل:
قد يكون كلا الخيارين مطلوبًا في حالات معينة (مثل السماح للمستخدمين بالاتصال بـ np.full
وإرجاع نتيجة رمزية حاليًا) ، ولكن إذا فهمت بشكل صحيح ، فإن الهدف من NEP-18 هو محاولة الحد عند الحاجة. والسماح للأشخاص باستخدام NumPy الأصلي في المزيد من الحالات.
أفهم أن هناك مقايضة أداء / تعقيد هنا وقد يكون ذلك سببًا جيدًا لعدم تنفيذ ذلك. ولكنه قد يجبر المستخدمين على استكشاف وسائل أخرى للحصول على المرونة التي يرغبون فيها.
هل هناك اقتراح حول إجراء هذا النوع من التغيير أم أنك تقول إن دعم إرسال
np.array
سيكون صعبًا حقًا ولذا لا يمكننا الحصول على دعم بنسبة 100٪؟
يناقش NEP 22 الخيارات هنا. لا أعتقد أنه يمكننا تغيير دلالات np.asarray()
بأمان لإرجاع أي شيء بخلاف كائن numpy.ndarray
- سنحتاج إلى بروتوكول جديد لهذا الغرض.
تكمن المشكلة في أن np.asarray()
حاليًا هو الطريقة الاصطلاحية للإرسال إلى كائن مصفوفة numpy ، والذي يستخدم ويتوقع أن يتطابق تمامًا مع numpy.ndarray
، على سبيل المثال ، وصولاً إلى تخطيط الذاكرة.
هناك بالتأكيد الكثير من حالات الاستخدام التي لم يكن هذا هو الحال فيها ، ولكن تبديل هذا السلوك قد يكسر الكثير من التعليمات البرمجية النهائية ، لذا فهي ليست بداية. ستحتاج مشاريع المصب إلى الاشتراك في هذا الجانب على الأقل من كتابة صفيف بطة.
أفهم أن هناك مقايضة أداء / تعقيد هنا وقد يكون ذلك سببًا جيدًا لعدم تنفيذ ذلك. ولكنه قد يجبر المستخدمين على استكشاف وسائل أخرى للحصول على المرونة التي يرغبون فيها.
نعم. لا يُقصد من NEP 18 أن يكون حلاً كاملاً لبدائل NumPy المنسدلة ، ولكنه خطوة في هذا الاتجاه.
لقد قمت بصياغة مراجعة لـ NEP-18 لإضافة سمة __numpy_implementation__
:
https://github.com/numpy/numpy/pull/13305
يخطر ببالي أننا ننسى تشويه الوظائف في numpy.testing
: https://github.com/numpy/numpy/issues/13588
سأفعل ذلك قريبًا ...
هناك مراجعة واحدة أود رؤيتها في NEP ، على وجه التحديد لتوضيح ما يضمن عروض NEP-18 لمؤلفي الفئات الفرعية: https://github.com/numpy/numpy/pull/13633
لقد حددت مهام قابلية الاستخدام مكتملة منذ أن تم إصلاح gh-13329. قررنا- # 13588 يمكن الانتظار حتى ما بعد إصدار 1.17. هذا يترك تحسينات الوثائق و arange
gh-12379 لا يزال مفتوحًا للتضمين في 1.17.
هناك أيضًا # 13728 - خطأ في المرسل مقابل histogram[2d]d
هذا يترك تحسينات الوثائق و arange gh-12379 لا يزال مفتوحًا للإدراج في 1.17.
كانت هناك مشكلة في التوثيق مفقودة ، لذلك فتحت gh-13844. أعتقد أن المستندات أهم بكثير من المشكلة المفتوحة arange
.
@ shoyer هل يمكننا إغلاق هذا؟
التعليق الأكثر فائدة
يناقش NEP 22 الخيارات هنا. لا أعتقد أنه يمكننا تغيير دلالات
np.asarray()
بأمان لإرجاع أي شيء بخلاف كائنnumpy.ndarray
- سنحتاج إلى بروتوكول جديد لهذا الغرض.تكمن المشكلة في أن
np.asarray()
حاليًا هو الطريقة الاصطلاحية للإرسال إلى كائن مصفوفة numpy ، والذي يستخدم ويتوقع أن يتطابق تمامًا معnumpy.ndarray
، على سبيل المثال ، وصولاً إلى تخطيط الذاكرة.هناك بالتأكيد الكثير من حالات الاستخدام التي لم يكن هذا هو الحال فيها ، ولكن تبديل هذا السلوك قد يكسر الكثير من التعليمات البرمجية النهائية ، لذا فهي ليست بداية. ستحتاج مشاريع المصب إلى الاشتراك في هذا الجانب على الأقل من كتابة صفيف بطة.
نعم. لا يُقصد من NEP 18 أن يكون حلاً كاملاً لبدائل NumPy المنسدلة ، ولكنه خطوة في هذا الاتجاه.