У меня есть фрагмент кода, который вычисляет позиции некоторых спутников и планет, используя Skyfield . Для ясности я использую Pandas DataFrame в качестве контейнера позиций и соответствующих моментов времени. Я хочу сделать расчет параллельно, но всегда получаю одну и ту же ошибку: TypeError: can't pickle Satrec objects
. Были протестированы различные параллелизаторы, такие как Dask, pandarallel , swifter и Pool.map ().
Пример куска кода для распараллеливания:
def get_sun_position(self, row):
t = self.ts.utc(row["Date"]) # from skyfield
pos = self.earth.at(t).observe(self.sun).apparent().position.m # from skyfield, error is here
return pos
def get_sat_position(self, row):
t = self.ts.utc(row["Date"]) # from skyfield
pos = self.sat.at(t).position.m # from skyfield, error is here
return pos
def get_positions(self):
self.df["sat_pos"] = self.df.swifter.apply(self.get_sat_position, axis=1) # all the parallelization goes here
self.df["sun_pos"] = self.df.swifter.apply(self.get_sun_position, axis=1) # and here
# the same implementation but using dask
# self.df["sat_pos"] = dd.from_pandas(self.df, npartitions=4*cpu_count())\
# .map_partitions(lambda df : df.apply(lambda row : self.get_sat_position(row),axis=1))\
# .compute(scheduler='processes')
# self.df["sun_pos"] = dd.from_pandas(self.df, npartitions=4*cpu_count())\
# .map_partitions(lambda df : df.apply(lambda row : self.get_sun_position(row),axis=1))\
# .compute(scheduler='processes')
Для Dask, чтобы избежать Pickle, я попытался вручную установить serializaton , как это serializers=['dask', 'pickle']
, но это не так Т помочь.
Как я понимаю, Skyfield использует sgp4 , который содержит класс Satre c.
Мне было бы интересно узнать, есть ли способ распараллелить это .apply()
. Или, может быть, мне вообще не стоит использовать функции Skyfield для параллельной обработки?