0

给定坐标(纬度/经度)和时间戳,我正在使用库为每个坐标/时间戳对计算太阳是否在该位置和时间升起skyfield

import datetime as dt

import numpy as np
from skyfield import almanac
from skyfield.api import Loader
from skyfield.toposlib import wgs84
from skyfield_data import get_skyfield_data_path


load = Loader(get_skyfield_data_path())
eph = load("de421.bsp")
ts = load.timescale()

# Made up times
datetimes = [
    dt.datetime(2000, 1, 1, tzinfo=dt.timezone.utc)
    + dt.timedelta(minutes=m) for m in range(24 * 60)
]
times = ts.from_datetimes(datetimes)

# Made up coordinates
coordinates = np.array([
    (50.0, lon)
    for lon in np.linspace(0.0, 30.0, 1000)
])

results = []
for lat, lon in coordinates:
    pos = wgs84.latlon(lat, lon)
    is_day = almanac.sunrise_sunset(eph, pos)
    results.append(is_day(times))

这段代码有效,但对我的需要来说太慢了。有没有办法将坐标上的 Python 循环移动到 NumPy 中?Skyfield 文档说 Skyfield 使用 NumPy,但据我所知wgs84.latlon,它没有将 NumPy 数组作为输入。

如果无法避免 Python 循环,是否有一种方法可以提高速度的准确性?

请注意,在我的实际用例中,时间戳和坐标都是用户提供的并且事先未知,因此我不能假设它们具有任何特定结构。

4

1 回答 1

0

多处理是 CPU 密集型活动的常见解决方案:这似乎是。

由于酸洗错误,无法跨多个进程共享eph 。这意味着每个进程都必须调用load()。但是,这似乎相对较快。以下代码在我的机器上运行约 3 秒。这可能会或可能不会比您当前的经验更好,因为您的原始问题中没有提到执行的持续时间。

import time
import datetime as dt
import numpy as np
from skyfield import almanac
from skyfield.api import Loader
from skyfield.toposlib import wgs84
from skyfield_data import get_skyfield_data_path
from concurrent.futures import ProcessPoolExecutor


load = Loader(get_skyfield_data_path())

ts = load.timescale()

# Made up times
datetimes = [
    dt.datetime(2000, 1, 1, tzinfo=dt.timezone.utc)
    + dt.timedelta(minutes=m) for m in range(24 * 60)
]
times = ts.from_datetimes(datetimes)

# Made up coordinates
coordinates = np.array([
    (50.0, lon)
    for lon in np.linspace(0.0, 30.0, 1000)
])


def docalc(lat, lon):
    pos = wgs84.latlon(lat, lon)
    eph = load('de421.bsp')
    return almanac.sunrise_sunset(eph, pos)(times)


def main():
    results = []
    with ProcessPoolExecutor() as executor:
        futures = []
        for lat, lon in coordinates:
            futures.append(executor.submit(docalc, lat, lon))
        for future in futures:
            results.append(future.result())
    return results


if __name__ == '__main__':
    s = time.perf_counter()
    main()
    e = time.perf_counter()
    print(f'Duration = {e-s:.4f}s')
于 2021-10-12T13:19:36.103 回答