Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Deepspeedai DeepSpeed Inference Context

From Leeroopedia


Knowledge Sources
Domains Inference, Memory_Management, Context_Management, CUDA
Last Updated 2026-02-09 00:00 GMT

Overview

Singleton context manager for inference operations providing workspace allocation, cuBLAS handle management, stream coordination, and KV-cache memory management.

Description

The InferenceContext class implements a singleton pattern that manages global state for DeepSpeed inference operations. It provides centralized workspace allocation with automatic sizing based on available GPU memory, model configuration (hidden size, number of heads/layers), and sequence length requirements. The workspace accommodates attention computations, KV-cache storage (optionally external), and intermediate activations with dynamic adjustment for prompt processing versus token generation. The class maintains a cuBLAS handle configured with tensor core math mode, manages CUDA streams for compute and communication operations with event-based synchronization, and tracks generation state including current token count and seed for random number generation. Memory allocation is lazy and can be released/retaken for flexible resource management in deployment scenarios.

Usage

Access the singleton instance when implementing inference kernels that need workspace memory, cuBLAS operations, or stream management. The context automatically handles memory constraints and provides diagnostic output for workspace sizing decisions, crucial for deploying large models efficiently.

Code Reference

Source Location

Signature

class InferenceContext {
public:
    static InferenceContext& Instance();

    // Workspace management
    void GenWorkSpace(const unsigned& num_layers,
                     const unsigned& num_heads,
                     const size_t& batch_size,
                     const size_t& prompt_len,
                     const size_t& hidden_dim,
                     const unsigned& mp_size,
                     const bool& external_cache,
                     const size_t& elem_size,
                     const unsigned& rank,
                     unsigned max_out_tokens,
                     unsigned min_out_tokens);

    void* GetWorkSpace();
    void* GetAttentionUnfusedWorkspace();
    size_t get_workspace_size() const;
    size_t GetMaxTokenLength() const;

    // cuBLAS management
    cublasHandle_t GetCublasHandle();

    // Stream management
    cudaStream_t GetCurrentStream(bool other_stream = false);
    cudaStream_t GetCommStream(bool async_op = false);
    void SynchComp();  // Synchronize compute and comm streams
    void SynchComm();

    // Generation state
    unsigned current_tokens() const;
    void advance_tokens();
    void reset_tokens(unsigned initial_tokens = 1);
    std::pair<uint64_t, uint64_t> IncrementOffset(uint64_t offset_inc);
    void SetSeed(uint64_t new_seed);

    // Workspace control
    void release_workspace();
    bool retake_workspace();
};

Import

#include "inference_context.h"

I/O Contract

Parameter Type Description
num_layers unsigned Number of transformer layers
num_heads unsigned Number of attention heads
batch_size size_t Batch size for inference
prompt_len size_t Initial prompt length
hidden_dim size_t Model hidden dimension
mp_size unsigned Model parallel size
max_out_tokens unsigned Maximum total sequence length
Output Type Description
workspace void* Allocated workspace pointer
cublas_handle cublasHandle_t Configured cuBLAS handle
streams cudaStream_t CUDA streams for operations

Usage Examples

Basic Context Initialization:

#include "inference_context.h"

// Model configuration
unsigned num_layers = 32;
unsigned num_heads = 32;
size_t hidden_dim = 4096;
size_t batch_size = 8;
size_t prompt_len = 512;
unsigned max_tokens = 2048;

// Initialize workspace
InferenceContext::Instance().GenWorkSpace(
    num_layers, num_heads, batch_size, prompt_len, hidden_dim,
    1,      // mp_size (no model parallelism)
    false,  // external_cache (manage internally)
    sizeof(__half),  // element size
    0,      // rank
    max_tokens,      // maximum sequence length
    prompt_len       // minimum sequence length
);

// Get workspace for kernel
void* workspace = InferenceContext::Instance().GetWorkSpace();
size_t workspace_size = InferenceContext::Instance().get_workspace_size();
printf("Allocated workspace: %.2f GB\n",
       (float)workspace_size / (1024*1024*1024));

Using cuBLAS Handle:

// Perform matrix multiplication using context's cuBLAS handle
void inference_matmul(__half* A, __half* B, __half* C,
                     int M, int N, int K) {
    auto handle = InferenceContext::Instance().GetCublasHandle();
    auto stream = InferenceContext::Instance().GetCurrentStream();

    cublasSetStream(handle, stream);

    float alpha = 1.0f, beta = 0.0f;
    cublas_gemm_ex(handle, CUBLAS_OP_N, CUBLAS_OP_N,
                   M, N, K, &alpha, &beta, A, B, C,
                   CUBLAS_GEMM_DEFAULT_TENSOR_OP);
}

Stream Coordination:

// Overlap computation with communication
void pipeline_forward(__half* input, __half* output,
                     __half* weights, int size) {
    auto comp_stream = InferenceContext::Instance().GetCurrentStream();
    auto comm_stream = InferenceContext::Instance().GetCommStream(true);

    // Launch computation on compute stream
    compute_kernel<<<blocks, threads, 0, comp_stream>>>(
        input, output, weights, size);

    // Synchronize compute before communication
    InferenceContext::Instance().SynchComp();

    // Launch communication (all-gather/all-reduce)
    communication_kernel<<<1, 1, 0, comm_stream>>>(output, size);

    // Wait for communication before next compute
    InferenceContext::Instance().SynchComm();
}

Token Generation Tracking:

class AutoregressiveGenerator {
    InferenceContext& ctx = InferenceContext::Instance();

public:
    void generate(int num_tokens_to_generate) {
        ctx.reset_tokens(1);  // Start with 1 token (BOS)

        for (int i = 0; i < num_tokens_to_generate; i++) {
            int current = ctx.current_tokens();
            printf("Generating token %d\n", current);

            // Forward pass generates next token
            forward_step();

            // Advance token counter
            ctx.advance_tokens();

            // Check if we've reached max sequence length
            if (ctx.current_tokens() > ctx.GetMaxTokenLength()) {
                fprintf(stderr, "Exceeded max sequence length!\n");
                break;
            }
        }
    }
};

Dynamic Workspace Allocation:

// Adjust workspace for different batch sizes
void reconfigure_workspace(size_t new_batch_size,
                          size_t new_seq_len) {
    auto& ctx = InferenceContext::Instance();

    // Release current workspace
    ctx.release_workspace();

    // Reconfigure with new parameters
    ctx.GenWorkSpace(
        32,  // num_layers
        32,  // num_heads
        new_batch_size,
        new_seq_len,  // prompt_len
        4096,  // hidden_dim
        1,  // mp_size
        false,  // external_cache
        sizeof(__half),
        0,  // rank
        2048,  // max_out_tokens
        new_seq_len  // min_out_tokens
    );

    // Verify workspace was reallocated
    if (!ctx.retake_workspace()) {
        throw std::runtime_error("Failed to reallocate workspace");
    }
}

Attention Workspace Management:

// Use separate workspace regions for different operations
__global__ void attention_kernel(__half* Q, __half* K, __half* V,
                                __half* output, int batch, int heads,
                                int seq_len, int head_dim) {
    // Main workspace for intermediate results
    __half* main_workspace = static_cast<__half*>(
        InferenceContext::Instance().GetWorkSpace());

    // Separate region for unfused attention operations
    __half* attn_workspace = static_cast<__half*>(
        InferenceContext::Instance().GetAttentionUnfusedWorkspace());

    // Use attn_workspace for attention scores
    __half* scores = attn_workspace;
    int scores_size = batch * heads * seq_len * seq_len;

    // Compute attention...
}

External KV-Cache Management:

// When KV-cache is managed externally (e.g., PagedAttention)
class ExternalCacheManager {
    void* kv_cache;
    size_t cache_size;

public:
    ExternalCacheManager(size_t batch, size_t max_seq,
                        size_t num_layers, size_t hidden) {
        // Allocate KV-cache separately
        cache_size = 2 * num_layers * batch * max_seq * hidden * sizeof(__half);
        cudaMalloc(&kv_cache, cache_size);

        // Initialize context with external_cache=true
        InferenceContext::Instance().GenWorkSpace(
            num_layers, hidden / 64, batch, 1, hidden,
            1, true,  // external_cache = true
            sizeof(__half), 0, max_seq, 1
        );
    }

    ~ExternalCacheManager() {
        cudaFree(kv_cache);
    }

    void* get_kv_cache() { return kv_cache; }
};

Memory-Constrained Deployment:

// Handle OOM gracefully
bool try_allocate_workspace(size_t batch, size_t seq_len,
                           size_t max_tokens) {
    try {
        InferenceContext::Instance().GenWorkSpace(
            32, 32, batch, seq_len, 4096,
            1, false, sizeof(__half), 0,
            max_tokens, seq_len
        );
        return true;
    } catch (const std::runtime_error& e) {
        // Workspace allocation failed (OOM)
        fprintf(stderr, "Workspace allocation failed: %s\n", e.what());

        // Try with smaller max_tokens
        if (max_tokens > seq_len * 2) {
            return try_allocate_workspace(batch, seq_len, max_tokens / 2);
        }
        return false;
    }
}

// Usage
if (!try_allocate_workspace(8, 512, 4096)) {
    fprintf(stderr, "Unable to allocate sufficient workspace\n");
    // Fall back to smaller batch or sequence length
}

Random Number Generation:

// Coordinate RNG state across operations
void set_generation_seed(uint64_t seed) {
    InferenceContext::Instance().SetSeed(seed);
}

__global__ void dropout_kernel(__half* data, uint8_t* mask,
                               int size, float ratio) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx >= size) return;

    // Get unique seed/offset for this operation
    auto [seed, offset] = InferenceContext::Instance().IncrementOffset(size);

    // Use seed/offset for curand initialization
    curandState state;
    curand_init(seed, idx, offset, &state);

    float rand_val = curand_uniform(&state);
    mask[idx] = (rand_val > ratio) ? 1 : 0;
    data[idx] = mask[idx] ? data[idx] / (1.0f - ratio) : 0.0f;
}

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment