Runpod Flash

repository·main·Indexed 41 days ago

https://github.com/runpod/flash

A Python SDK and library (v1.19.0) for developing cloud-native AI applications. Flash enables distributed inference and serving of machine learning models by allowing developers to define hardware requirements, remote functions, and dependencies in local Python code, automating GPU provisioning, scaling, and deployment on Runpod Serverless.

Tokens
45.8K
Snippets
149
Records
215
Agent score
51%

What's inside Flash

  1. What is a Flash environment?

    main

    An environment is an isolated deployment context within a Flash app, acting as a separate "stage" (e.g., dev, staging, or production). Each environment is independent and contains its own:

    • Deployed endpoints: Serverless endpoints provisioned from your Endpoint definitions.
    • Active build version: The specific version of your code running in that environment.
    • Network volumes: Persistent storage for models, caches, etc.
    • Deployment state: The current status (e.g., PENDING, DEPLOYING, DEPLOYED, FAILED).

    Environments allow you to test changes in dev, validate in staging, and then promote to production without affecting other stages. Note that running flash deploy --env <name> will automatically create the environment if it does not already exist.

    Flash App (my-project)
    ├── Environment: dev
    │   ├── Build: build_v1
    │   ├── Endpoints: [ep1, ep2]
    │   └── Volumes: [vol1]
    ├── Environment: staging
    │   ├── Build: build_v2
    │   ├── Endpoints: [ep1, ep2]
    │   └── Volumes: [vol1]
    └── Environment: production
        ├── Build: build_v2
        ├── Endpoints: [ep1, ep2]
        └── Volumes: [vol1]
  2. What is a Flash app?

    main

    A Flash app is a top-level organizational unit (a cloud-side container) that groups all resources related to a single project. It acts as a namespace in Runpod to keep your deployment environments, build artifacts, and configurations organized.

    Key components within an app:

    • Environments: Isolated deployment contexts (e.g., dev, staging, production) that contain endpoints and volumes.
    • Builds: Versioned artifacts created from your code that environments reference to run specific versions.
    • Configuration: App-wide settings and metadata.

    Isolation: Different apps do not share resources, each has its own quota, limits, and access controls.

    Flash App (my-project)
    │
    ├── Environments
    │   ├── dev
    │   │   ├── Endpoints (ep1, ep2)
    │   │   └── Volumes (vol1)
    │   ├── staging
    │   │   ├── Endpoints (ep1, ep2)
    │   │   └── Volumes (vol1)
    │   └── production
    │       ├── Endpoints (ep1, ep2)
    │       └── Volumes (vol1)
    │
    └── Builds
        ├── build_v1 (2024-01-15)
        ├── build_v2 (2024-01-18)
        └── build_v3 (2024-01-20)
  3. Manage concurrency and scaling in LB Endpoints

    main

    Runpod scales workers based on the REQUEST_COUNT scaler. When active requests exceed a defined threshold, new workers are provisioned; they scale down after an idle_timeout when requests drop.

    Concurrency Patterns:

    • Asynchronous functions (async def): Can handle multiple requests concurrently within a single worker thread. This is highly efficient for I/O-bound tasks.
    • Synchronous functions (def): Block the worker thread and are processed one at a time per worker.
    @api.post("/api/process")
    async def process_data(x: int):
        import asyncio
        await asyncio.sleep(10)  # simulate work
        return {"result": x}
    
    # 5 concurrent requests:
    # requests 1-3: concurrent on worker 1 (async)
    # requests 4-5: concurrent on worker 2 (new worker)
    # all 5 complete in ~10s
  4. Configure Python versions for Flash apps

    main

    Flash apps ship as a single tarball where all resources share one Python version. The worker runtime defaults to 3.12 (optimized for Torch in the GPU base image).

    You can select a different version in two ways:

    1. Per-resource declaration: Set python_version="3.11" on any resource config. All resources in the same app must use the same version or leave it unset.
    2. App-level override: Pass --python-version <version> to flash build or flash deploy. This override takes precedence over unset per-resource values.
    VersionStatusGPU cold-startNotes
    3.10Supported+torch reinstallConsider migrating to 3.11
    3.11Supported+torch reinstall
    3.12Supported (default)No overheadTorch pre-installed
    3.13Supported+torch reinstallRequires torch ≥2.5.0

    Note: Non-3.12 targets incur overhead due to torch wheel reinstallation for the matching ABI, not an alternate-interpreter install.

  5. How Load-Balanced (LB) Workers work

    main

    Load-Balanced (LB) workers expose standard HTTP endpoints (GET, POST, etc.) behind a load balancer. These are designed for low-latency API endpoints that require horizontal scaling.

    To define an LB worker, instantiate an Endpoint object with a name, cpu type, and a workers tuple defining the scaling range (e.g., workers=(1, 3)). You then use this instance as a decorator for your route handlers.

    Example LB Worker:

    from runpod_flash import Endpoint
    
    api = Endpoint(name="lb_worker", cpu="cpu3c-1-2", workers=(1, 3))
    
    @api.post("/process")
    async def process(input_data: dict) -> dict:
        return {"status": "success", "echo": input_data}
    
    @api.get("/health")
    async def health() -> dict:
        return {"status": "healthy"}
    from runpod_flash import Endpoint
    
    api = Endpoint(name="lb_worker", cpu="cpu3c-1-2", workers=(1, 3))
    
    @api.post("/process")
    async def process(input_data: dict) -> dict:
        return {"status": "success", "echo": input_data}
  6. How Flash works: Core Concepts

    main

    Flash provides several key capabilities for cloud-native AI development:

    • Remote Execution: @Endpoint functions run on Runpod Serverless GPUs/CPUs.
    • Implicit Endpoint Resolution: When you run python script.py, Flash automatically routes calls to your deployed endpoints based on name and environment.
    • Auto-scaling: Workers scale from 0 to N based on demand.
    • Dependency Management: Specified dependencies are automatically installed on remote workers.
    • Concurrency Control: Use max_concurrency to allow a single worker to process multiple jobs simultaneously.
    • Two Patterns:
      • Queue-based: Use @Endpoint for batch/asynchronous work.
      • Load-balanced: Use Endpoint() + routes for REST APIs.
  7. Understand CPU vs GPU endpoint defaults and behavior

    main

    CPU and GPU endpoints in Flash differ in their base Docker images and default disk allocations:

    • CPU Endpoints: Use python:*-slim base images and default to 20GB of container disk.
    • GPU Endpoints: Use pytorch/pytorch:* base images and default to 10GB of container disk.

    When using PodTemplate, Flash performs a field-level merge: explicit fields in your template override the defaults, while unset fields inherit the resource class defaults.

  8. Manage dependency installation and cross-platform builds

    main

    Flash handles cross-platform builds automatically to ensure compatibility with Runpod's Linux x86_64 infrastructure:

    • Platform Targeting: Dependencies are always installed for Linux x86_64, regardless of whether you build on macOS, Windows, or Linux.
    • Python Version: Targets Python 3.12 for wheel ABI selection regardless of your local interpreter.
    • Binary Wheels: Only pre-built binary wheels are used to prevent platform-specific compilation issues.

    Optimizing Package Size

    Runpod Serverless has a 1.5GB limit on deployment archives. To stay under this limit:

    1. Use --no-deps to only install direct dependencies specified in Endpoint definitions.
    2. Use --exclude to skip packages already present in your base image (e.g., torch, torchvision, torchaudio for GPU images).
  9. How cross-endpoint function calls work

    main

    When your application contains functions on multiple endpoints (e.g., a CPU preprocessor and a GPU inference engine), the build process generates a manifest that enables automatic service discovery and routing. This allows functions to call each other directly by name.

    # CPU endpoint function
    @Endpoint(name="preprocessor", cpu="cpu3c-4-8")
    def preprocess(data):
        return clean_data
    
    # GPU endpoint function
    @Endpoint(name="inference", gpu=GpuGroup.AMPERE_80)
    async def inference(data):
        # calls CPU endpoint function via the generated manifest
        clean = preprocess(data)
        return results
    from runpod_flash import Endpoint, GpuGroup
    
    @Endpoint(name="preprocessor", cpu="cpu3c-4-8")
    def preprocess(data):
        return clean_data
    
    @Endpoint(name="inference", gpu=GpuGroup.AMPERE_80)
    async def inference(data):
        clean = preprocess(data)
        return results
  10. How class-based Queue-based (QB) endpoints work

    main

    When you use the @Endpoint(...) decorator on a class, Flash treats it as a class-based queue-based endpoint.

    Key behaviors:

    • Singleton Lifecycle: The class is instantiated exactly once per worker.
    • Method Dispatching: Requests are dispatched to specific methods within the class.
    • Dispatch Logic:
      • Single-method classes: Automatically dispatch to the available method.
      • Multi-method classes: Require a method key in the input JSON to specify which method to call.

    Example of the generated handler logic:

    from module_path import ClassName
    
    _instance = ClassName()
    _METHODS = {"predict": _instance.predict, "embed": _instance.embed}
    
    def handler(job):
        job_input = job["input"]
        method_name = job_input.pop("method", None)
        method = _METHODS[method_name]
        return method(**job_input)
    # Example of how a multi-method class is invoked via the handler
    # Input JSON:
    # {"input": {"method": "predict", "data": "..."}}
  11. How Flash detects and overrides apps

    main

    The Flash CLI automatically detects the app name based on your current working directory or local configuration.

    If you need to target a specific app that is not the one detected by the current directory, you can override this behavior using the --app flag in your commands.

    # In project directory, app is auto-detected
    flash deploy
    
    # Overriding the detected app
    flash deploy --app other-project
    flash env list --app other-project
  12. Understand CPU LoadBalancer drift detection constraints

    main

    CPU LoadBalancers use a specialized hashing mechanism that only considers CPU-relevant fields. This prevents false drift detection when GPU-specific fields are set to their defaults.

    Included fields for CPU LB hash:

    • datacenter
    • flashboot
    • imageName
    • networkVolume
    • instanceIds
    • workersMin
    • workersMax
    • scalerType
    • scalerValue
    • type
    • idleTimeout
    • executionTimeoutMs
    • locations

    Excluded fields:

    • GPU-specific fields such as gpuIds, gpuCount, allowedCudaVersions, and minCudaVersion are explicitly ignored to avoid unnecessary updates.