Numpy: ์ž˜๋ชป๋œ ๋ชจ์–‘์— ๋Œ€ํ•œ gufunc ๋™์ž‘

์— ๋งŒ๋“  2020๋…„ 06์›” 02์ผ  ยท  5์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: numpy/numpy

์—ฌ๊ธฐ ํ† ๋ก ์—์„œ : https://github.com/numpy/numpy/pull/15162#discussion_r434122175

๋‹ค์Œ ์˜ˆ์ œ๋Š” ์•„์›ƒ ์…ฐ์ดํ”„๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๊ฑฐ๋‚˜ ์ž…๋ ฅ์„ ์ถœ๋ ฅ์— ๋ธŒ๋กœ๋“œ ์บ์ŠคํŠธ ํ•  ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ ๊ฒฐ๊ณผ + ๊ฐ€๋น„์ง€ ๊ฐ’์œผ๋กœ ์•„์›ƒ์„ ์ž๋™์œผ๋กœ ์ฑ„ ์›๋‹ˆ๋‹ค.

import numpy as np
from numpy.core import _umath_tests as umt
from numpy.testing import assert_raises
a = np.arange(6).reshape(3, 2)
b = np.ones(2)
out = np.empty((5, 3))
umt.inner1d(a, b, out)
print(out)

๊ฒฐ๊ณผ:

[[ 1.00000000e+000  5.00000000e+000  9.00000000e+000]
 [ 6.91217735e-310 -1.45681599e+144 -1.45681599e+144]
 [-1.45681599e+144 -1.45681599e+144 -1.45681599e+144]
 [-1.45681599e+144 -1.45681599e+144 -1.45681599e+144]
 [-1.45681599e+144 -1.45681599e+144  6.32404027e-322]]
00 - Bug numpy.core numpy.ufunc

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์•„, ์•„์ฃผ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 19876d641..85820e3a0 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2614,7 +2614,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
      * dimensions.
      */
     broadcast_ndim = 0;
-    for (i = 0; i < nin; ++i) {
+    for (i = 0; i < nop; ++i) {
         int n = PyArray_NDIM(op[i]) - op_core_num_dims[i];
         if (n > broadcast_ndim) {
             broadcast_ndim = n;

์•„๋งˆ ๊ทธ๊ฒŒ ์ „๋ถ€์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์šฐ๋ฆฌ๋Š” ์ถœ๋ ฅ์— ๋Œ€ํ•œ ์ž…๋ ฅ์˜ ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ์†ก์„ ์–ป์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์„ ๋น„๋‚œํ•˜๋Š” ์ƒ๊ฐ์€ ๋ฏธ๋ž˜์˜ ์ž์‹ ์„ ์œ„ํ•ด ์—ฐ๊ธฐ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๊ฒŒ๋‹ค๊ฐ€ op์˜ null ๊ฒ€์‚ฌ ...

๋ชจ๋“  5 ๋Œ“๊ธ€

Hehe, ์ž ์‹œ ๋™์•ˆ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ณ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜น์‹œ๋ผ๋„ @mhvk๋ฅผ ํ•‘ํ•ฉ๋‹ˆ๋‹ค.

NPY_ITER_NO_BROADCAST ํ”Œ๋ž˜๊ทธ๋Š” ์ด์ƒํ•˜๊ฒŒ๋„ ๋ชจ์–‘ ๊ฒ€์ƒ‰์„ ์œ„ํ•ด ํ•ด๋‹น ํ”ผ์—ฐ์‚ฐ์ž๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฑฐ์˜ ํ•ญ์ƒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค (์˜ˆ : ์ถœ๋ ฅ ์ž‘์—…). ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ํœด์‹์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ƒˆ๋กœ์šด NPY_ITER_OUTPUT_OPERAND ์ถ”๊ฐ€๋ฅผ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” NPY_ITER_OUTPUT_OPERAND ๋ฐ ๋‹ค๋ฅธ ํ”Œ๋ž˜๊ทธ NPY_ITER_DOES_NOT_AFFECT_SHAPE ๋ฅผ ๋งŒ๋“ค์–ด ์ถœ๋ ฅ ํ”ผ์—ฐ์‚ฐ์ž ํ”Œ๋ž˜๊ทธ๊ฐ€ "allocate"๋ฐ "no broadcast"ํ”Œ๋ž˜๊ทธ๋ฅผ ๋ชจ๋‘ ํฌํ•จ ํ•  ์ˆ˜ ์žˆ๋„๋กํ•ฉ๋‹ˆ๋‹ค.

ํ• ๋‹น๊ณผ ๋ฐฉ์†ก ๊ธˆ์ง€์˜ ์กฐํ•ฉ์ฒ˜๋Ÿผ ๋Š๊ปด์ง€๋ฉฐ, ์•„๋งˆ๋„ ์ด๋ฏธ ์ด๊ฒƒ์„ ์•”์‹œํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฌธ์ œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋Ÿฌํ•œ ๋ณ€๊ฒฝ์„ ์›ํ•œ๋‹ค๋ฉด ์ด๋ก ์ ์œผ๋กœ NpyIter๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์‹œ์ž‘ํ•  ๋•Œ VisibleDeprecationWarning์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š” ํ•œ, ๊ตฌํ˜„ํ•˜๊ธฐ์— ๋งค์šฐ ๊น”๋”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์ถ•๊ณผ ๊ฐ™์€ ํฅ๋ฏธ๋กœ์šด ๋ถ€์ˆ˜์  ์ธ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. (์–ธ์  ๊ฐ€๋Š”?) ๊ทธ๊ฒƒ์„ ์ง€์›ํ•˜๋ ค๊ณ  ์‹œ๋„ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค์ œ ์ด๋“์„ ์–ป์ง€ ๋ชปํ•˜๋„๋ก ๋„ˆ๋ฌด ๋ณต์žก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
(),()->(k) gufunc์— ๋Œ€ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋งŽ์ด ๋ณด์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. (),()->(3,3) ๋˜๋Š” ->(3,3) ์™€ ๊ฐ™์€ ๊ฒƒ์€ ๋‹น์—ฐํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊นƒ๋ฐœ์— ๋Œ€ํ•ด ์•ฝ๊ฐ„ ํ˜ผ๋ž€์Šค๋Ÿฌ์›Œ์„œ ์ธ์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ()->(k) ์„œ๋ช…์ด์žˆ๋Š” gufunc moments ๋Š” ์ถœ๋ ฅ์—์„œ โ€‹โ€‹์ตœ๋Œ€ k ๊นŒ์ง€ ์ˆœ๊ฐ„์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก , ์—„์ฒญ๋‚˜๊ฒŒ ๋ฌด๋ฆฌ๊ฐ€ ์žˆ์ง€๋งŒ, ์ œ ๊ฐ๊ฐ์€ ๊ทธ๊ฒƒ์„ ๋ช…์‹œ ์ ์œผ๋กœ ๋ฐฐ์ œํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค (๋ช…์‹œ ์ ์œผ๋กœ ๊ทธ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋Š” ์ฝ”๋“œ๋„ ์•„๋‹™๋‹ˆ๋‹ค!).

์ถœ๋ ฅ์ด ์ผ๊ด€๋˜์ง€ ์•Š์€ ์™ธ๋ถ€ ๋ชจ์–‘์„ ๊ฐ–๋Š” ๋ฌธ์ œ์™€ ๋” ์ง์ ‘์ ์œผ๋กœ ๊ด€๋ จ์ด์žˆ๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜ ufuncs์˜ ์ „๋ก€๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

np.add(1, 1, out=np.empty((3,)))
# array([2., 2., 2.])

์ด๊ฒƒ์€ gufuncs์˜ ๊ฒฝ์šฐ์—๋„ ๋ชจ๋“  ์ž…๋ ฅ ๋ฐ ์ถœ๋ ฅ์—์„œ โ€‹โ€‹์™ธ๋ถ€ ๋ชจ์–‘์„ ๊ฒฐ์ •ํ•ด์•ผ ํ•จ์„ ์‹œ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ ๋ถˆํ•„์š”ํ•œ ๊ณ„์‚ฐ์„ ์œ ๋ฐœํ•  ๊ฒƒ์ด์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ค, ์–ด๋–ป๊ฒŒ ๋“  ๊ทธ๊ฒƒ์ด ์‹ค์ œ๋กœ ์ž‘๋™ ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ถœ๋ ฅ์ด ์ž…๋ ฅ์—์„œ ๋ธŒ๋กœ๋“œ ์บ์ŠคํŒ…์„ ์œ ๋ฐœํ•˜๋„๋ก ํ—ˆ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค (๋”ฐ๋ผ์„œ ๋ชจ์–‘์„ ์กฐ์ •). ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹จ์ˆœํžˆ ํ˜„์žฌ ๋™์ž‘์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

(g) ufunc๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ์•„๋ฌด ์ž‘์—…๋„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (๋งŽ์€ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๋ฅผ ์–ป๋Š” ๋ฐ ์•ฝ๊ฐ„์˜ ๋Š๋ฆฐ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ํ˜ธ์ถœ์ž ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค). ์ด๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ gufuncs์—์„œ์ด ๋ฌธ์ œ๋ฅผ ๋ถ„๋ช…ํžˆ ๊ณ ์ณ์•ผํ•ฉ๋‹ˆ๋‹ค!

์•„, ์•„์ฃผ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 19876d641..85820e3a0 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2614,7 +2614,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
      * dimensions.
      */
     broadcast_ndim = 0;
-    for (i = 0; i < nin; ++i) {
+    for (i = 0; i < nop; ++i) {
         int n = PyArray_NDIM(op[i]) - op_core_num_dims[i];
         if (n > broadcast_ndim) {
             broadcast_ndim = n;

์•„๋งˆ ๊ทธ๊ฒŒ ์ „๋ถ€์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์šฐ๋ฆฌ๋Š” ์ถœ๋ ฅ์— ๋Œ€ํ•œ ์ž…๋ ฅ์˜ ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ์†ก์„ ์–ป์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์„ ๋น„๋‚œํ•˜๋Š” ์ƒ๊ฐ์€ ๋ฏธ๋ž˜์˜ ์ž์‹ ์„ ์œ„ํ•ด ์—ฐ๊ธฐ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๊ฒŒ๋‹ค๊ฐ€ op์˜ null ๊ฒ€์‚ฌ ...

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰