Improved CPU knobs
This commit is contained in:
+42
-25
@@ -20,32 +20,52 @@ _assets_config: Optional[dict] = None
|
|||||||
_perf_config: Optional[dict] = None
|
_perf_config: Optional[dict] = None
|
||||||
|
|
||||||
|
|
||||||
def get_ffmpeg_thread_count() -> int:
|
def _load_perf_config() -> dict:
|
||||||
"""Return FFmpeg thread count based on [performance] cpu_limit in ~/.gnommo.conf.
|
"""Read and cache the [performance] section of ~/.gnommo.conf."""
|
||||||
|
|
||||||
cpu_limit is a fraction of logical CPUs (e.g. 0.8 = 80%).
|
|
||||||
Defaults to 1 when not configured, which is safe on memory-constrained machines.
|
|
||||||
|
|
||||||
Example ~/.gnommo.conf:
|
|
||||||
[performance]
|
|
||||||
cpu_limit = 0.8
|
|
||||||
"""
|
|
||||||
global _perf_config
|
global _perf_config
|
||||||
if _perf_config is None:
|
if _perf_config is not None:
|
||||||
config_path = Path.home() / ".gnommo.conf"
|
return _perf_config
|
||||||
_perf_config = {}
|
|
||||||
if config_path.exists():
|
_perf_config = {}
|
||||||
cfg = configparser.ConfigParser()
|
config_path = Path.home() / ".gnommo.conf"
|
||||||
cfg.read(config_path)
|
if config_path.exists():
|
||||||
if cfg.has_option("performance", "cpu_limit"):
|
cfg = configparser.ConfigParser()
|
||||||
|
cfg.read(config_path)
|
||||||
|
for key in ("cpu_limit_preprocess", "cpu_limit_render", "cpu_limit"):
|
||||||
|
if cfg.has_option("performance", key):
|
||||||
try:
|
try:
|
||||||
_perf_config["cpu_limit"] = float(
|
_perf_config[key] = float(cfg.get("performance", key))
|
||||||
cfg.get("performance", "cpu_limit")
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
if cfg.has_option("performance", "render_chunk_slides"):
|
||||||
|
try:
|
||||||
|
_perf_config["render_chunk_slides"] = int(
|
||||||
|
cfg.get("performance", "render_chunk_slides")
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return _perf_config
|
||||||
|
|
||||||
cpu_limit = _perf_config.get("cpu_limit")
|
|
||||||
|
def get_ffmpeg_thread_count(stage: str = "preprocess") -> int:
|
||||||
|
"""Return the FFmpeg thread count for a pipeline stage from ~/.gnommo.conf.
|
||||||
|
|
||||||
|
Preprocessing and rendering scale differently, so they read separate CPU
|
||||||
|
fractions of the logical core count:
|
||||||
|
|
||||||
|
[performance]
|
||||||
|
cpu_limit_preprocess = 0.8 # throughput-bound; safe at high parallelism
|
||||||
|
cpu_limit_render = 0.15 # -filter_complex spawns swscaler threads per
|
||||||
|
# layer and OOMs at high core counts
|
||||||
|
|
||||||
|
`stage` is "preprocess" or "render". The legacy single `cpu_limit` key is the
|
||||||
|
fallback for either stage when its specific key is absent. Each value is a
|
||||||
|
fraction of logical CPUs (0.8 = 80%); defaults to 1 thread when nothing is
|
||||||
|
configured, which is safe on memory-constrained machines.
|
||||||
|
"""
|
||||||
|
cfg = _load_perf_config()
|
||||||
|
key = "cpu_limit_render" if stage == "render" else "cpu_limit_preprocess"
|
||||||
|
cpu_limit = cfg.get(key, cfg.get("cpu_limit"))
|
||||||
if cpu_limit is None:
|
if cpu_limit is None:
|
||||||
return 1
|
return 1
|
||||||
cpu_count = os.cpu_count() or 1
|
cpu_count = os.cpu_count() or 1
|
||||||
@@ -62,10 +82,7 @@ def get_render_chunk_size() -> Optional[int]:
|
|||||||
[performance]
|
[performance]
|
||||||
render_chunk_slides = 15
|
render_chunk_slides = 15
|
||||||
"""
|
"""
|
||||||
global _perf_config
|
val = _load_perf_config().get("render_chunk_slides")
|
||||||
if _perf_config is None:
|
|
||||||
get_ffmpeg_thread_count() # populates _perf_config
|
|
||||||
val = _perf_config.get("render_chunk_slides")
|
|
||||||
if val is None:
|
if val is None:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ from typing import Union, Optional
|
|||||||
|
|
||||||
|
|
||||||
def _tc() -> str:
|
def _tc() -> str:
|
||||||
"""Return FFmpeg thread count string from ~/.gnommo.conf [performance] cpu_limit."""
|
"""FFmpeg thread count for preprocessing (~/.gnommo.conf cpu_limit_preprocess)."""
|
||||||
from .cache import get_ffmpeg_thread_count
|
from .cache import get_ffmpeg_thread_count
|
||||||
|
|
||||||
return str(get_ffmpeg_thread_count())
|
return str(get_ffmpeg_thread_count("preprocess"))
|
||||||
|
|
||||||
|
|
||||||
# Number of parallel workers for chunk processing
|
# Number of parallel workers for chunk processing
|
||||||
|
|||||||
+1
-1
@@ -447,7 +447,7 @@ def build_ffmpeg_command(plan: RenderPlan, output_path: Path) -> list[str]:
|
|||||||
# thread per core no matter what — the real cause of the render-stage memory blowup.
|
# thread per core no matter what — the real cause of the render-stage memory blowup.
|
||||||
from .cache import get_ffmpeg_thread_count
|
from .cache import get_ffmpeg_thread_count
|
||||||
|
|
||||||
_tc = str(get_ffmpeg_thread_count())
|
_tc = str(get_ffmpeg_thread_count("render"))
|
||||||
cmd.extend(
|
cmd.extend(
|
||||||
["-threads", _tc, "-filter_threads", _tc, "-filter_complex_threads", _tc]
|
["-threads", _tc, "-filter_threads", _tc, "-filter_complex_threads", _tc]
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user