0

我有一段代码使用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,我尝试像这样手动 设置序列化serializers=['dask', 'pickle'],但没有帮助。

据我了解,Skyfield 使用包含Satrec 类的 sgp4。

我想知道是否有某种方法可以并行化它.apply()。或者也许我根本不应该尝试使用 Skyfield 函数进行并行处理?

4

1 回答 1

0

唉,你用来使计算并行的所有机制都是通过创建另一个进程然后将计算中涉及的所有对象的副本发送到另一个进程来实现的——并且该Satrec对象是用 C++ 编写的,而不是 Python,为了使其更快,C++ 对象没有本地方式将自己“序列化”为字节以传输到另一个进程。(Python 对象内置了这种能力。)

您是否对代码进行了概要分析以查看最昂贵的步骤是什么?我的猜测是,您的大部分费用都花在了太阳计算上,因为要实现其高精度 Skyfield 需要以非常高的精度计算地球的方位,以使太阳在天空中的位置即使对于射电天文学家来说也具有足够高的精度。

但是,如果您自己不需要那么高的精度,您可以切换到太阳的低精度天空坐标。在使用tin之前get_sun_position(),请尝试对它执行以下操作:

t._nutation_angles = iau2000b(t.tt)

这将使用对地球章动的较低精度估计(打印出此更改前后的值以查看差异有多大,并将其与您的应用程序可以承受的不准确性进行比较),但也希望运行得更快。

于 2020-04-02T13:14:12.833 回答