В моделировании методом Монте-Карло я создаю множество списков случайных координат палочки (фактически два списка координат для повторения, представляющих два разных типа палок) в форме [[x0,y0,x1,y1]*N]
. Используя векторизованные методы numpy, я попытался свести к минимуму время создания. Однако при определенных условиях длина массивов превышает 10 миллионов, а генерация становится узким местом.Эффективный способ создания множества случайных координат палочки с numpy
Следующий код дает минимальный пример с некоторым тестом значением
import numpy as np
def create_coordinates_vect(dimensions=[1500,2500], length=50, count=12000000, type1_content=0.001):
# two arrays with random start coordinates in area of dimensions
x0 = np.random.randint(dimensions[0], size=count)
y0 = np.random.randint(dimensions[1], size=count)
# random direction of each stick
dirrad = 2 * np.pi * np.random.rand(count)
# to destinguish between type1 and type2 sticks based on random values
stick_type = np.random.rand(count)
is_type1 = np.zeros_like(stick_type)
is_type1[stick_type < type1_content] = True
# calculate end coordinates
x1 = x0 + np.rint(np.cos(dirrad) * length).astype(np.int32)
y1 = y0 + np.rint(np.sin(dirrad) * length).astype(np.int32)
# stack together start and end coordinates
coordinates = np.vstack((x0, y0, x1, y1)).T.astype(np.int32)
# split array according to type
coords_type1 = coordinates[is_type1 == True]
coords_type2 = coordinates[is_type1 == False]
return ([coords_type1, coords_type2])
list1, list2 = create_coordinates_vect()
Анализ времени дает следующие результаты для различных секций
=> x0, y0: 477.3640632629945 ms
=> dirrad, stick_type: 317.4648284911094 ms
=> is_type1: 27.3699760437172 ms
=> x1, y1: 1184.7038269042969 ms
=> vstack: 189.0783309965234 ms
=> coords_type1, coords_type2: 309.9758625035176 ms
я все еще мог получить некоторое время, определяя количество типов type1 и type2, вместо того, чтобы делать какое-то случайное сравнение чисел для каждой палочки. Тем не менее, сохраняется более длинная часть создания случайных начальных координат и направления плюс расчет конечных координат.
Кто-нибудь видит дальнейшие оптимизации, чтобы ускорить создание массивов?
Спасибо. Раньше я не знал о 'numexpr'. Действительно, это ускоряет создание 'x1' и' y1', и оно уже установлено как на Anaconda для Windows, так и на Ubuntu. – MrCyclophil