skyfielders / python-skyfield

Elegant astronomy for Python
MIT License
1.41k stars 212 forks source link

.at(t) exhibits unusually high CPU usage in Ubuntu #916

Closed PeterS-mBryonics closed 10 months ago

PeterS-mBryonics commented 10 months ago

This one has me a bit stumped. Running test code on Windows, all is well and good. Running the same code on Linux on two different computers (One WSL, one native, both Ubuntu 22.04) results in unusually high CPU usage across all cores while the code is running. Minimal example below:

import time
from skyfield.api import load, wgs84

ts = load.timescale()

bluffton = wgs84.latlon(+40.8939, -83.8917)

t = ts.now()
i = 0
sec = 0
while i < 100:
    t += 1 / 86400
    topocentric = bluffton.at(t)
    time.sleep(0.25)
    i += 1

Adjusting the time.sleep affects the overall processor load (removing it maxes out all cores). Each CPU is loaded relatively evenly which is not what I was expecting - as far as I understand it this should be single-threaded. Running two of these programs at once when it's arranged such that one program maxes out the computer does slow them down, so it doesn't appear to be the CPU loading lying to me which was my first thought. Having the slightly weird t+1s bit in the loop is so I can be sure I'm not muddling things by calling ts.now() repeatedly.

I would have expected the CPU usage to go up and down, it only visibly does that at about a sleep time of 0.75 s. I feel like I'm missing something obvious, so I'm happy to be proved a muppet!

brandon-rhodes commented 10 months ago

See whether OpenBLAS might be the culprit:

https://rhodesmill.org/skyfield/accuracy-efficiency.html#using-too-many-cpu-cores

Let us know if the fix suggested there affects the behavior you are seeing!

PeterS-mBryonics commented 10 months ago
RTFM! Knew I missed something... A solution for those that are looking, add this to the top of the file, _before_ importing numpy (including skyfield!). An alternative is changing environment variables or a change to .bashrc but I'm 90% sure I'd forget I'd done that and go through the whole thing again. ``` import os os.environ['OPENBLAS_NUM_THREADS'] = '1' os.environ['MKL_NUM_THREADS'] = '1' ``` This dealt with the issue
brandon-rhodes commented 10 months ago

@PeterS-mBryonics — I have just landed 9c4edda956453b298b24f824ad11db2aa5918472 which updates the Skyfield docs to mention both of these settings, instead of just the first one, and so that the docs also show your maneuver of setting the environment variables right in Python (thanks for the idea!).

I'm glad that the settings worked for you!