Мне нужно рассчитать зенитный угол Солнца примерно для 106 000 000 различных координат. Эти координаты относятся к пикселям изображения, проецируемого на поверхность Земли после того, как изображение было снято камерой в самолете.
Я использую pvlib.solarposition.get_position() для расчета зенитного угла Солнца. Возвращаемые значения рассчитываются правильно (я сравнил некоторые результаты с веб-сайтом NOOA), но, как мне нужно рассчитать угол солнечного зенита для многих пар координат, питон тратит много дней (около 5 дней), чтобы завершить выполнение функции .
Как я новичок в программировании, интересно, есть ли способ ускорить расчет зенитного угла солнца.
Ниже приведена часть реализованного кода, которая вычисляет зенитный угол Солнца:
sol_apar_zen = []
for i in range(size3):
solar_position = np.array(pvl.solarposition.get_solarposition(Data_time_index, lat_long[i][0], lat_long[i][1]))
sol_apar_zen.append(solar_position[0][0])
print(len(sol_apar_zen))
Я запускаю алгоритм для 10 000 координат. Зенитный угол Солнца для этих координат вычислялся за 1 мин 12 с. Для 100 000 координат программа потратила 12 минут и 2 секунды на вычисление зенитного угла Солнца.
Судя по данным 10k, 106M должно занять ~8 дней. Итак, похоже, библиотека просто требует времени. Пара вариантов: найти параметры настройки, ускоряющие вычисления, или найти другую библиотеку. Кроме того, если расчеты для каждой координаты независимы, вы можете рассмотреть возможность разделения набора данных и выполнения их одновременно (как отдельные процессы) в хорошей многоядерной системе.
Какова длина Data_time_index
? solarposition.get_solarposition
— это оболочка для нескольких различных алгоритмов определения положения солнца. Большинство реализаций предназначены для эффективного многократного вычисления положения солнца по одной координате. Похоже, вы хотите сделать обратное: эффективно вычислить положение Солнца за один (или относительно небольшой) раз по многим координатам. 10 000 раз для одной координаты на большинстве машин должно занять меньше секунды.
@WillHolmgren Data_time_index содержит только одно значение, потому что оно относится к времени (времени и дате), когда камера сделала одно изображение. Я так думаю, что лучше найти другую библиотеку для расчета солнечного зенитного угла. Если вы или другой коллега знаете об одной библиотеке, дайте мне знать, пожалуйста!!
Возможно, в модуле pvlib.spa можно использовать низкоуровневые ускоренные функции pvlib numba. Другой вариант — использовать функции pvlib.solarposition.*_analytical
— большинство из них принимают массивы ndim, но мне не сразу очевидно, как заставить вычисление часового угла работать для вашего варианта использования. Пожалуйста, напишите ответ ниже, если вы найдете решение.
Если вы хотите ускорить этот расчет, вы можете использовать ядро numba (если оно установлено)
location.get_solarposition(
datetimes,
method='nrel_numba'
)
В противном случае вам придется реализовать свой собственный расчет на основе векторизованных массивов numpy. Я знаю, что это возможно, но мне не разрешено делиться. Вы можете найти формулировку, если вы ищете spencer 1971 solar position
Поскольку ваши координаты представляют собой сетку, другим вариантом будет вычисление зенитного угла для подмножества ваших координат и выполнение двумерной интерполяции для получения остатка. 1 из 100 в обоих направлениях сократит время расчета в 10 000 раз.
Технически, если вам нужно быстро вычислить солнечный зенитный угол для большого списка (массива), существуют более эффективные алгоритмы, чем алгоритм PVLIB. Например, описанный Роберто Греной в 2012 году (https://doi.org/10.1016/j.solener.2012.01.024).
Я нашел подходящую реализацию здесь: https://github.com/david-salac/Fast-SZA-and-SAA-computation (вам нужны некоторые настройки, но ее просто использовать, плюс она также реализована для других языков, кроме Python, таких как C/C++ и Go).
Пример того, как его использовать:
from sza_saa_grena import solar_zenith_and_azimuth_angle
# ...
# A random time series:
time_array = pd.date_range("2020/1/1", periods=87_600, freq = "10T", tz = "UTC")
sza, saa = solar_zenith_and_azimuth_angle(longitude=-0.12435, # London longitude
latitude=51.48728, # London latitude
time_utc=time_array)
Тот юнит-тест (в папке проекта) показывает, что в нормальном диапазоне широт ошибка минимальна.
Первый шаг, который я бы сделал, — изолировать проблему производительности между моим кодом и кодом библиотеки. Один из способов сделать это — рассчитать время, скажем, по 1000 координатам. С такими небольшими числами маловероятно, что неэффективность структур данных проявится, и это должно дать меру библиотечного кода. Если общее время, затрачиваемое на 106M координат, примерно в 10^5 раз больше, чем на 1k координат, то вполне вероятно, что код библиотеки работает долго. Если общее время значительно больше этого, сосредоточьтесь на обертывании кода.