NAME
Lugh::Context - Memory Context for Tensor Allocation
VERSION
Version 0.01
SYNOPSIS
use Lugh;
# Create a context with 16 MB of memory
my $ctx = Lugh::Context->new(mem_size => 16 * 1024 * 1024);
# Create tensors in this context
my $a = Lugh::Tensor->new_f32($ctx, 1024);
my $b = Lugh::Tensor->new_f32($ctx, 1024);
# Tensors are automatically freed when context goes out of scope
DESCRIPTION
Lugh::Context provides memory management for tensor allocation. It wraps ggml's context system, which uses a memory arena for efficient allocation of many tensors without individual malloc/free overhead.
Memory Arena
When you create a Context, a contiguous block of memory is allocated. All tensors created in that context share this memory arena:
Context (16 MB arena)
┌─────────────────────────────────────────────────┐
│ Tensor A (4KB) │ Tensor B (16KB) │ Tensor C ... │
└─────────────────────────────────────────────────┘
Benefits:
Fast allocation - No system malloc per tensor
Cache friendly - Tensors are contiguous in memory
Simple cleanup - Free entire context at once
Context Types
There are several common patterns for context usage:
Weight context - Long-lived, holds model weights (read from GGUF)
Compute context - Short-lived, holds computation graph tensors
Scratch context - Temporary, holds intermediate values
For high-level inference, you typically don't need to manage contexts directly - Lugh::Model and Lugh::Inference handle this internally.
CONSTRUCTOR
new
my $ctx = Lugh::Context->new(
mem_size => $bytes
);
Creates a new memory context.
Parameters:
mem_size(required) - Size of memory arena in bytes
Returns: A Lugh::Context object.
Throws: Dies if memory allocation fails or if maximum contexts exceeded.
Memory Sizing:
The memory size should account for:
Tensor metadata (about 256 bytes per tensor)
Tensor data (depends on type and dimensions)
Alignment padding
Rule of thumb: allocate 2-3× the expected tensor data size.
Example:
# Small context for a few tensors
my $ctx = Lugh::Context->new(mem_size => 1024 * 1024); # 1 MB
# Large context for model weights
my $ctx = Lugh::Context->new(mem_size => 1024 * 1024 * 1024); # 1 GB
METHODS
mem_size
my $bytes = $ctx->mem_size;
Returns the total size of the memory arena.
mem_used
my $bytes = $ctx->mem_used;
Returns the amount of memory currently used by tensors.
Example:
my $ctx = Lugh::Context->new(mem_size => 1024 * 1024);
print "Used: ", $ctx->mem_used, " bytes\n"; # Initially small
my $tensor = Lugh::Tensor->new_f32($ctx, 1000);
print "Used: ", $ctx->mem_used, " bytes\n"; # +4000 bytes for data
MEMORY MANAGEMENT
Automatic Cleanup
When a Context object goes out of scope, its destructor automatically frees the entire memory arena:
{
my $ctx = Lugh::Context->new(mem_size => 1024 * 1024);
my $tensor = Lugh::Tensor->new_f32($ctx, 1000);
# ... use tensor ...
}
# $ctx is freed here, including all tensors
Warning: Never use a tensor after its context has been freed!
Maximum Contexts
There is a compile-time limit on the number of simultaneous contexts (default: 4096). This is rarely an issue in practice.
No Individual Tensor Free
You cannot free individual tensors within a context. This is by design - the arena allocator trades flexibility for speed. If you need to free tensors individually, use separate contexts.
TENSOR CREATION
Tensors are created using the static methods on Lugh::Tensor, passing the context as the first argument:
my $f32_1d = Lugh::Tensor->new_f32($ctx, 100);
my $f32_2d = Lugh::Tensor->new_f32($ctx, 100, 200);
my $f32_3d = Lugh::Tensor->new_f32($ctx, 100, 200, 300);
my $f32_4d = Lugh::Tensor->new_f32($ctx, 100, 200, 300, 400);
Memory usage for F32 tensors:
Dimensions Elements Memory
(100) 100 400 bytes
(100, 200) 20,000 80 KB
(100, 200, 300) 6,000,000 24 MB
LOW-LEVEL OPERATIONS
For advanced users, contexts can be used with the low-level Lugh::Ops and Lugh::Graph modules:
my $ctx = Lugh::Context->new(mem_size => 10 * 1024 * 1024);
my $a = Lugh::Tensor->new_f32($ctx, 1000);
my $b = Lugh::Tensor->new_f32($ctx, 1000);
$a->set_f32(1.0, 2.0, 3.0, ...);
$b->set_f32(4.0, 5.0, 6.0, ...);
my $c = Lugh::Ops::add($ctx, $a, $b);
my $graph = Lugh::Graph->new($ctx);
$graph->build_forward($c);
$graph->compute($ctx, 4); # 4 threads
my @result = $c->get_f32();
THREAD SAFETY
Lugh::Context objects are NOT thread-safe. The internal registry uses mutex locks, but individual contexts should not be shared across Perl threads. Each thread must create its own contexts.
For multi-threaded computation, use $graph->compute($ctx, $n_threads) which parallelizes within a single Perl thread using pthreads.
IMPLEMENTATION NOTES
Registry Pattern
Contexts are tracked in a global registry using integer IDs. This allows safe Perl object destruction and thread cloning:
Perl SV → Magic → ID → Registry → LughContext → ggml_context
ggml Context
Internally, this wraps struct ggml_context* from the ggml library. The ggml context provides:
Memory arena management
Tensor allocation
Computation graph building
Thread-safe graph execution
SEE ALSO
Lugh, Lugh::Tensor, Lugh::Graph, Lugh::Ops
https://github.com/ggerganov/ggml - ggml library
AUTHOR
lnation <email@lnation.org>
LICENSE
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 43:
Non-ASCII character seen before =encoding in '┌─────────────────────────────────────────────────┐'. Assuming UTF-8