@mytec: iter3.7.0 start, gpu calc int
This commit is contained in:
305
installer/rfcp-server-gpu.spec
Normal file
305
installer/rfcp-server-gpu.spec
Normal file
@@ -0,0 +1,305 @@
|
||||
# rfcp-server-gpu.spec — GPU-enabled build (CuPy + CUDA 13.x)
|
||||
# RFCP Iteration 3.6.0
|
||||
#
|
||||
# Mode: ONEDIR (directory output, not single exe)
|
||||
# This is better for CUDA — DLLs load directly without temp extraction
|
||||
#
|
||||
# Requirements:
|
||||
# pip install cupy-cuda13x fastrlock pyinstaller
|
||||
# CUDA Toolkit 13.x installed (winget install Nvidia.CUDA)
|
||||
#
|
||||
# Build:
|
||||
# cd backend && pyinstaller ../installer/rfcp-server-gpu.spec --clean --noconfirm
|
||||
#
|
||||
# Output:
|
||||
# backend/dist/rfcp-server/rfcp-server.exe (+ DLLs in same folder)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
from PyInstaller.utils.hooks import collect_all, collect_dynamic_libs
|
||||
|
||||
backend_path = os.path.abspath(os.path.join(os.path.dirname(SPEC), '..', 'backend'))
|
||||
print(f"[GPU SPEC] Backend path: {backend_path}")
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# Collect CuPy packages
|
||||
# ═══════════════════════════════════════════
|
||||
cupy_datas = []
|
||||
cupy_binaries = []
|
||||
cupy_hiddenimports = []
|
||||
cupyb_datas = []
|
||||
cupyb_binaries = []
|
||||
cupyb_hiddenimports = []
|
||||
|
||||
try:
|
||||
cupy_datas, cupy_binaries, cupy_hiddenimports = collect_all('cupy')
|
||||
cupyb_datas, cupyb_binaries, cupyb_hiddenimports = collect_all('cupy_backends')
|
||||
print(f"[GPU SPEC] CuPy: {len(cupy_binaries)} binaries, {len(cupy_datas)} data files")
|
||||
except Exception as e:
|
||||
print(f"[GPU SPEC] WARNING: CuPy collection failed: {e}")
|
||||
|
||||
# NOTE: nvidia pip packages REMOVED - they have cuda12 DLLs that conflict with cupy-cuda13x
|
||||
# We use CUDA Toolkit 13.x DLLs only
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# Collect CUDA Toolkit DLLs (system install)
|
||||
# ═══════════════════════════════════════════
|
||||
# Installed via: winget install Nvidia.CUDA
|
||||
cuda_toolkit_binaries = []
|
||||
cuda_path = os.environ.get('CUDA_PATH', '')
|
||||
|
||||
if cuda_path:
|
||||
# Scan BOTH bin\ and bin\x64\ directories
|
||||
cuda_bin_dirs = [
|
||||
os.path.join(cuda_path, 'bin'),
|
||||
os.path.join(cuda_path, 'bin', 'x64'),
|
||||
]
|
||||
|
||||
# Only essential CUDA runtime DLLs (exclude NPP, nvjpeg, nvblas, nvfatbin)
|
||||
cuda_dll_patterns = [
|
||||
'cublas64_*.dll',
|
||||
'cublasLt64_*.dll',
|
||||
'cudart64_*.dll',
|
||||
'cufft64_*.dll',
|
||||
'cufftw64_*.dll',
|
||||
'curand64_*.dll',
|
||||
'cusolver64_*.dll',
|
||||
'cusolverMg64_*.dll',
|
||||
'cusparse64_*.dll',
|
||||
'nvrtc64_*.dll',
|
||||
'nvrtc-builtins64_*.dll',
|
||||
'nvJitLink_*.dll',
|
||||
'nvjitlink_*.dll',
|
||||
]
|
||||
|
||||
collected_dlls = set() # Avoid duplicates
|
||||
for cuda_bin in cuda_bin_dirs:
|
||||
if os.path.isdir(cuda_bin):
|
||||
for pattern in cuda_dll_patterns:
|
||||
for dll in glob.glob(os.path.join(cuda_bin, pattern)):
|
||||
dll_name = os.path.basename(dll)
|
||||
if dll_name not in collected_dlls:
|
||||
cuda_toolkit_binaries.append((dll, '.'))
|
||||
collected_dlls.add(dll_name)
|
||||
print(f"[GPU SPEC] Scanned: {cuda_bin}")
|
||||
|
||||
print(f"[GPU SPEC] CUDA Toolkit ({cuda_path}): {len(cuda_toolkit_binaries)} DLLs")
|
||||
for dll, _ in cuda_toolkit_binaries:
|
||||
print(f"[GPU SPEC] {os.path.basename(dll)}")
|
||||
else:
|
||||
print("[GPU SPEC] ERROR: CUDA_PATH not set!")
|
||||
print("[GPU SPEC] Install: winget install Nvidia.CUDA")
|
||||
|
||||
# All GPU binaries (CUDA Toolkit only, no nvidia pip packages)
|
||||
all_gpu_binaries = cuda_toolkit_binaries
|
||||
|
||||
if len(all_gpu_binaries) == 0:
|
||||
print("[GPU SPEC] ⚠ NO CUDA DLLs FOUND!")
|
||||
print("[GPU SPEC] Install CUDA Toolkit: winget install Nvidia.CUDA")
|
||||
else:
|
||||
print(f"[GPU SPEC] ✅ Total GPU DLLs: {len(all_gpu_binaries)}")
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# Collect fastrlock (CuPy dependency)
|
||||
# ═══════════════════════════════════════════
|
||||
fl_datas = []
|
||||
fl_binaries = []
|
||||
fl_hiddenimports = []
|
||||
try:
|
||||
fl_datas, fl_binaries, fl_hiddenimports = collect_all('fastrlock')
|
||||
print(f"[GPU SPEC] fastrlock: {len(fl_binaries)} binaries")
|
||||
except Exception:
|
||||
print("[GPU SPEC] fastrlock not found (optional)")
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# PyInstaller Analysis
|
||||
# ═══════════════════════════════════════════
|
||||
|
||||
a = Analysis(
|
||||
[os.path.join(backend_path, 'run_server.py')],
|
||||
pathex=[backend_path],
|
||||
binaries=(
|
||||
cupy_binaries + cupyb_binaries +
|
||||
fl_binaries + all_gpu_binaries
|
||||
),
|
||||
datas=[
|
||||
# Include app/ source code
|
||||
(os.path.join(backend_path, 'app'), 'app'),
|
||||
] + cupy_datas + cupyb_datas + fl_datas,
|
||||
hiddenimports=[
|
||||
# ── Uvicorn internals ──
|
||||
'uvicorn.logging',
|
||||
'uvicorn.loops',
|
||||
'uvicorn.loops.auto',
|
||||
'uvicorn.loops.asyncio',
|
||||
'uvicorn.protocols',
|
||||
'uvicorn.protocols.http',
|
||||
'uvicorn.protocols.http.auto',
|
||||
'uvicorn.protocols.http.h11_impl',
|
||||
'uvicorn.protocols.http.httptools_impl',
|
||||
'uvicorn.protocols.websockets',
|
||||
'uvicorn.protocols.websockets.auto',
|
||||
'uvicorn.protocols.websockets.wsproto_impl',
|
||||
'uvicorn.lifespan',
|
||||
'uvicorn.lifespan.on',
|
||||
'uvicorn.lifespan.off',
|
||||
# ── FastAPI / Starlette ──
|
||||
'fastapi',
|
||||
'fastapi.middleware',
|
||||
'fastapi.middleware.cors',
|
||||
'fastapi.routing',
|
||||
'fastapi.responses',
|
||||
'fastapi.exceptions',
|
||||
'starlette',
|
||||
'starlette.routing',
|
||||
'starlette.middleware',
|
||||
'starlette.middleware.cors',
|
||||
'starlette.responses',
|
||||
'starlette.requests',
|
||||
'starlette.concurrency',
|
||||
'starlette.formparsers',
|
||||
'starlette.staticfiles',
|
||||
# ── Pydantic ──
|
||||
'pydantic',
|
||||
'pydantic.fields',
|
||||
'pydantic_settings',
|
||||
'pydantic_core',
|
||||
# ── HTTP / networking ──
|
||||
'httpx',
|
||||
'httpcore',
|
||||
'h11',
|
||||
'httptools',
|
||||
'anyio',
|
||||
'anyio._backends',
|
||||
'anyio._backends._asyncio',
|
||||
'sniffio',
|
||||
# ── MongoDB (motor/pymongo) ──
|
||||
'motor',
|
||||
'motor.motor_asyncio',
|
||||
'pymongo',
|
||||
'pymongo.errors',
|
||||
'pymongo.collection',
|
||||
'pymongo.database',
|
||||
'pymongo.mongo_client',
|
||||
# ── Async I/O ──
|
||||
'aiofiles',
|
||||
'aiofiles.os',
|
||||
'aiofiles.ospath',
|
||||
# ── Scientific ──
|
||||
'numpy',
|
||||
'numpy.core',
|
||||
'scipy',
|
||||
'scipy.special',
|
||||
'scipy.interpolate',
|
||||
'shapely',
|
||||
'shapely.geometry',
|
||||
'shapely.ops',
|
||||
# ── Multipart ──
|
||||
'multipart',
|
||||
'python_multipart',
|
||||
# ── Encoding ──
|
||||
'email.mime',
|
||||
'email.mime.multipart',
|
||||
# ── Multiprocessing ──
|
||||
'multiprocessing',
|
||||
'multiprocessing.pool',
|
||||
'multiprocessing.queues',
|
||||
'concurrent.futures',
|
||||
# ── CuPy + CUDA ──
|
||||
'cupy',
|
||||
'cupy.cuda',
|
||||
'cupy.cuda.runtime',
|
||||
'cupy.cuda.driver',
|
||||
'cupy.cuda.memory',
|
||||
'cupy.cuda.stream',
|
||||
'cupy.cuda.device',
|
||||
'cupy._core',
|
||||
'cupy._core.core',
|
||||
'cupy._core._routines_math',
|
||||
'cupy._core._routines_logic',
|
||||
'cupy._core._routines_manipulation',
|
||||
'cupy._core._routines_sorting',
|
||||
'cupy._core._routines_statistics',
|
||||
'cupy._core._cub_reduction',
|
||||
'cupy.fft',
|
||||
'cupy.linalg',
|
||||
'cupy.random',
|
||||
'cupy_backends',
|
||||
'cupy_backends.cuda',
|
||||
'cupy_backends.cuda.api',
|
||||
'cupy_backends.cuda.libs',
|
||||
'fastrlock',
|
||||
'fastrlock.rlock',
|
||||
] + cupy_hiddenimports + cupyb_hiddenimports + fl_hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[os.path.join(os.path.dirname(SPEC), 'rthook_cuda_dlls.py')],
|
||||
# ── Exclude bloat ──
|
||||
excludes=[
|
||||
# GUI
|
||||
'tkinter',
|
||||
'matplotlib',
|
||||
'PIL',
|
||||
'IPython',
|
||||
# Data science bloat
|
||||
'pandas',
|
||||
'tensorflow',
|
||||
'torch',
|
||||
'keras',
|
||||
# Testing
|
||||
'pytest',
|
||||
|
||||
# Jupyter
|
||||
'jupyter',
|
||||
'notebook',
|
||||
'ipykernel',
|
||||
# gRPC / telemetry (often pulled in by dependencies)
|
||||
'grpc',
|
||||
'grpcio',
|
||||
'google.protobuf',
|
||||
'opentelemetry',
|
||||
'opentelemetry.sdk',
|
||||
'opentelemetry.instrumentation',
|
||||
# Ray (too heavy, we use multiprocessing)
|
||||
'ray',
|
||||
# Other
|
||||
'cv2',
|
||||
'sklearn',
|
||||
'sympy',
|
||||
],
|
||||
noarchive=False,
|
||||
)
|
||||
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
# ═══════════════════════════════════════════
|
||||
# ONEDIR mode: EXE + COLLECT
|
||||
# ═══════════════════════════════════════════
|
||||
# Creates: dist/rfcp-server/rfcp-server.exe + all DLLs in same folder
|
||||
# Better for CUDA — no temp extraction needed
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[], # No binaries/datas in EXE — they go in COLLECT
|
||||
exclude_binaries=True, # ONEDIR mode
|
||||
name='rfcp-server',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=False, # Don't compress — CUDA libs need fast loading
|
||||
console=True,
|
||||
icon=os.path.join(os.path.dirname(SPEC), 'rfcp.ico') if os.path.exists(os.path.join(os.path.dirname(SPEC), 'rfcp.ico')) else None,
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=False,
|
||||
upx_exclude=[],
|
||||
name='rfcp-server',
|
||||
)
|
||||
Reference in New Issue
Block a user