что происходит под капотом вещания массива - PullRequest
3 голосов
/ 12 марта 2019

Я изучил стандартную документацию Python по вещанию https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html

Каждый раз, когда я изучаю эту тему, я не мог найти достаточно внутренних деталей о том, как вещание работает в реальности, имеет ли оно какое-то отношение к векторизации?

в соответствии с документами, широковещание - это эффективная операция с памятью, и она не делает фактическое копирование в памяти, поэтому как работает арифметическое вычисление внутри,

любой исходный код или любые источники, которые говорят оконцепция под капотом поможет прояснить мои сомнения.

1 Ответ

1 голос
/ 12 марта 2019

Простая иллюстрация трансляции - 1d со скаляром:

In [18]: x = np.arange(10)                                                      
In [19]: X,Y = np.broadcast_arrays(x,3)                                         
In [20]: X                                                                      
Out[20]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [21]: Y                                                                      
Out[21]: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])
In [22]: Y.strides                                                              
Out[22]: (0,)
In [23]: X+Y                                                                    
Out[23]: array([ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12])
In [24]: [i+j for i,j in zip(X,Y)]                                              
Out[24]: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

При такой конструкции трудно доказать, что Y не занимает столько памяти, сколько x. Итак, давайте расширим x вместо:

In [30]: x1 = np.broadcast_to(x,(3,10))                                         
In [31]: x1                                                                     
Out[31]: 
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
In [32]: x.__array_interface__                                                  
Out[32]: 
{'data': (30797968, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (10,),
 'version': 3}
In [33]: x1.__array_interface__                                                 
Out[33]: 
{'data': (30797968, True),
 'strides': (0, 8),
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (3, 10),
 'version': 3}

x1 акций x буфер данных. Дополнительная память не используется (за исключением самого объекта массива).

И превратить скаляр в 2d:

In [34]: x2,y2 = np.broadcast_arrays(x1,Y)                                      
In [35]: y2.strides                                                             
Out[35]: (0, 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...