Skip to main content

GPU Config Wiring - Implementation Plan

Task: Wire GPU configuration from TOML → NPU → Backend Selection
Estimated Time: 1-2 weeks
Complexity: Low (straightforward integration)


Step-by-Step Implementation

Step 1: Create GpuConfig in feagi-burst-engine

File: feagi-core/crates/feagi-burst-engine/src/backend/mod.rs

Add after line 247 (after BackendConfig definition):

/// GPU configuration from TOML (simplified interface for burst engine)
#[derive(Debug, Clone)]
pub struct GpuConfig {
/// Enable GPU processing
pub use_gpu: bool,

/// Enable hybrid CPU/GPU auto-selection
pub hybrid_enabled: bool,

/// Threshold in synapses to consider GPU (hybrid mode)
pub gpu_threshold: usize,

/// Fraction of GPU memory to use (0.0-1.0)
pub gpu_memory_fraction: f64,
}

impl Default for GpuConfig {
fn default() -> Self {
Self {
use_gpu: true,
hybrid_enabled: true,
gpu_threshold: 1_000_000,
gpu_memory_fraction: 0.8,
}
}
}

impl GpuConfig {
/// Convert to BackendConfig and BackendType for backend selection
pub fn to_backend_config(&self) -> (BackendType, BackendConfig) {
let backend_type = if !self.use_gpu {
// GPU explicitly disabled
BackendType::CPU
} else if self.hybrid_enabled {
// Hybrid mode: auto-select based on genome size
BackendType::Auto
} else {
// GPU always on (if available)
#[cfg(feature = "gpu")]
{
BackendType::WGPU
}
#[cfg(not(feature = "gpu"))]
{
tracing::warn!("GPU requested but 'gpu' feature not enabled, falling back to CPU");
BackendType::CPU
}
};

let backend_config = BackendConfig {
gpu_neuron_threshold: self.gpu_threshold / 100, // Rough estimate: 100 synapses/neuron
gpu_synapse_threshold: self.gpu_threshold,
force_cpu: !self.use_gpu,
force_gpu: self.use_gpu && !self.hybrid_enabled,
..Default::default()
};

(backend_type, backend_config)
}
}

Testing:

#[cfg(test)]
mod gpu_config_tests {
use super::*;

#[test]
fn test_gpu_disabled() {
let config = GpuConfig {
use_gpu: false,
..Default::default()
};
let (backend_type, backend_config) = config.to_backend_config();
assert_eq!(backend_type, BackendType::CPU);
assert!(backend_config.force_cpu);
}

#[test]
fn test_gpu_hybrid_mode() {
let config = GpuConfig {
use_gpu: true,
hybrid_enabled: true,
gpu_threshold: 500_000,
..Default::default()
};
let (backend_type, backend_config) = config.to_backend_config();
assert_eq!(backend_type, BackendType::Auto);
assert_eq!(backend_config.gpu_synapse_threshold, 500_000);
}

#[test]
#[cfg(feature = "gpu")]
fn test_gpu_always_on() {
let config = GpuConfig {
use_gpu: true,
hybrid_enabled: false,
..Default::default()
};
let (backend_type, _) = config.to_backend_config();
assert_eq!(backend_type, BackendType::WGPU);
}
}

Step 2: Update RustNPU::new() to Accept GPU Config

File: feagi-core/crates/feagi-burst-engine/src/npu.rs

Current signature (around line 100):

pub fn new(
neuron_capacity: usize,
synapse_capacity: usize,
cortical_area_count: usize,
) -> Self

Updated signature:

pub fn new(
neuron_capacity: usize,
synapse_capacity: usize,
cortical_area_count: usize,
gpu_config: Option<&backend::GpuConfig>, // NEW PARAMETER
) -> Self {
use tracing::info;

// Determine backend based on GPU config
let (backend_type, backend_config) = if let Some(config) = gpu_config {
config.to_backend_config()
} else {
// No config provided: default to CPU
(backend::BackendType::CPU, backend::BackendConfig::default())
};

info!("🎮 Creating NPU with backend: {}", backend_type);
if let Some(config) = gpu_config {
info!(" GPU enabled: {}", config.use_gpu);
info!(" Hybrid mode: {}", config.hybrid_enabled);
info!(" GPU threshold: {} synapses", config.gpu_threshold);
}

// Create backend
let backend = backend::create_backend(
backend_type,
neuron_capacity,
synapse_capacity,
&backend_config,
).expect("Failed to create compute backend");

info!(" ✓ Backend selected: {}", backend.backend_name());

// Rest of NPU initialization (unchanged)
Self {
neuron_array: NeuronArray::new(neuron_capacity),
synapse_array: SynapseArray::new(synapse_capacity),
fire_candidate_list: FireCandidateList::new(neuron_capacity),
fire_queue: FireQueue::new(neuron_capacity),
fire_ledger: FireLedger::new(neuron_capacity),
cortical_areas: vec![CorticalAreaId(0); cortical_area_count],
burst_count: 0,
backend, // Use the selected backend
}
}

Also update import_connectome() (around line 250):

pub fn import_connectome(connectome: Connectome) -> Self {
Self::import_connectome_with_config(connectome, None)
}

pub fn import_connectome_with_config(
connectome: Connectome,
gpu_config: Option<&backend::GpuConfig>,
) -> Self {
// Create NPU with GPU config
let mut npu = Self::new(
connectome.neurons.capacity,
connectome.synapses.capacity,
connectome.cortical_area_names.len(),
gpu_config, // Pass GPU config
);

// Import data
npu.neuron_array = connectome.neurons;
npu.synapse_array = connectome.synapses;
// ... rest unchanged

npu
}

Step 3: Wire Config in feagi/src/main.rs

File: /Users/nadji/code/FEAGI-2.0/feagi/src/main.rs

Add import at top (after line 26):

use feagi_burst_engine::backend::GpuConfig;

Update NPU initialization (replace lines 152-160):

// Initialize NPU with GPU configuration
info!(" Initializing NPU...");

// Create GPU config from TOML settings
let gpu_config = GpuConfig {
use_gpu: config.resources.use_gpu,
hybrid_enabled: config.neural.hybrid.enabled,
gpu_threshold: config.neural.hybrid.gpu_threshold,
gpu_memory_fraction: config.resources.gpu_memory_fraction,
};

info!(" GPU Configuration:");
info!(" - GPU enabled: {}", gpu_config.use_gpu);
info!(" - Hybrid mode: {}", gpu_config.hybrid_enabled);
info!(" - GPU threshold: {} synapses", gpu_config.gpu_threshold);
info!(" - GPU memory fraction: {:.1}%", gpu_config.gpu_memory_fraction * 100.0);

let npu = Arc::new(Mutex::new(RustNPU::new(
config.connectome.neuron_space,
config.connectome.synapse_space,
10, // cortical_area_count - will be resized as needed
Some(&gpu_config), // Pass GPU config
)));

info!(" ✓ NPU initialized (capacity: {} neurons, {} synapses)",
config.connectome.neuron_space,
config.connectome.synapse_space);

Update genome loading (replace lines 226-256 in load_genome function):

async fn load_genome(
manager: &Arc<RwLock<ConnectomeManager>>,
genome_path: &PathBuf,
) -> Result<()> {
use feagi_evolutionary::{load_genome_from_file, validate_genome};

// Load genome from file
let genome = load_genome_from_file(genome_path)
.context("Failed to load genome file")?;

// Validate genome
let validation = validate_genome(&genome);
if !validation.errors.is_empty() {
error!("Genome validation errors:");
for error in &validation.errors {
error!(" - {}", error);
}
return Err(anyhow::anyhow!("Genome validation failed"));
}

if !validation.warnings.is_empty() {
warn!("Genome validation warnings:");
for warning in &validation.warnings {
warn!(" - {}", warning);
}
}

// Load genome into connectome (includes neuroembryogenesis)
// Note: GPU backend will be auto-selected based on resulting genome size
manager.write().load_from_genome(genome)
.context("Failed to load genome into connectome")?;

// Log backend selection result after genome is loaded
info!(" Backend selection completed based on genome size");

Ok(())
}

Step 4: Update feagi-inference-engine Similarly

File: /Users/nadji/code/FEAGI-2.0/feagi-inference-engine/src/main.rs

Add after line 6:

use feagi_burst_engine::backend::GpuConfig;

Add CLI argument (after line 64):

/// Enable GPU acceleration (default: auto-detect based on brain size)
#[arg(long, default_value_t = true)]
gpu_enabled: bool,

/// GPU threshold in synapses (default: 1000000)
#[arg(long, default_value_t = 1000000)]
gpu_threshold: usize,

Update NPU creation (replace line 124):

// Create NPU from connectome with GPU config
info!("Initializing NPU with GPU configuration...");

let gpu_config = GpuConfig {
use_gpu: args.gpu_enabled,
hybrid_enabled: true,
gpu_threshold: args.gpu_threshold,
gpu_memory_fraction: 0.8,
};

info!(" GPU enabled: {}", gpu_config.use_gpu);
info!(" GPU threshold: {} synapses", gpu_config.gpu_threshold);

let mut npu = feagi_burst_engine::RustNPU::import_connectome_with_config(
connectome,
Some(&gpu_config),
);

info!("✓ NPU initialized successfully!");

Step 5: Testing the Integration

Test 1: GPU Disabled

Config (feagi_configuration.toml):

[resources]
use_gpu = false

Expected Output:

🎮 Creating NPU with backend: CPU
GPU enabled: false
✓ Backend selected: CPU (SIMD)

Command:

./target/release/feagi --config feagi_configuration.toml --genome test_genome.json

Test 2: GPU Hybrid Mode (Small Genome)

Config:

[neural.hybrid]
enabled = true
gpu_threshold = 1000000

[resources]
use_gpu = true

Genome: 100K neurons, 10M synapses (below threshold)

Expected Output:

🎮 Creating NPU with backend: Auto
GPU enabled: true
Hybrid mode: true
GPU threshold: 1000000 synapses
🎯 Backend auto-selection: CPU (Small genome: 100000 neurons, 10000000 synapses)
✓ Backend selected: CPU (SIMD)

Test 3: GPU Hybrid Mode (Large Genome)

Genome: 2M neurons, 200M synapses (above threshold)

Expected Output:

🎮 Creating NPU with backend: Auto
GPU enabled: true
Hybrid mode: true
GPU threshold: 1000000 synapses
🎯 Backend auto-selection: WGPU (Large genome: 2000000 neurons, 200000000 synapses)
Estimated speedup: 8.5x
🎮 Using WGPU backend (GPU accelerated)
✓ Backend selected: WGPU (Apple M4 Pro - Metal)

Test 4: GPU Always On

Config:

[neural.hybrid]
enabled = false # Disable auto-selection

[resources]
use_gpu = true

Expected Output:

🎮 Creating NPU with backend: WGPU
GPU enabled: true
Hybrid mode: false
🎮 Using WGPU backend (GPU accelerated)
✓ Backend selected: WGPU (Apple M4 Pro - Metal)

Test 5: GPU Feature Not Compiled

Build without GPU:

cargo build --release # Without --features gpu

Config:

[resources]
use_gpu = true

Expected Output:

🎮 Creating NPU with backend: CPU
GPU enabled: true
⚠️ GPU requested but 'gpu' feature not enabled, falling back to CPU
✓ Backend selected: CPU (SIMD)

Step 6: Update Cargo.toml Feature Flags

File: /Users/nadji/code/FEAGI-2.0/feagi/Cargo.toml

Add after line 33 (in dependencies section):

# GPU acceleration (optional, enabled by default)
feagi-burst-engine = { path = "../feagi-core/crates/feagi-burst-engine", features = ["gpu"] }

Add features section (after line 53):

[features]
default = ["gpu"]
gpu = ["feagi-burst-engine/gpu"]

Build commands:

# With GPU (default)
cargo build --release

# Without GPU (CPU only)
cargo build --release --no-default-features

# Explicit GPU
cargo build --release --features gpu

Step 7: Verification

Check 1: Config Parsing

# Verify config is read correctly
./target/release/feagi --config feagi_configuration.toml 2>&1 | grep -A5 "GPU Configuration"

Expected:

GPU Configuration:
- GPU enabled: true
- Hybrid mode: true
- GPU threshold: 1000000 synapses
- GPU memory fraction: 80.0%

Check 2: Backend Selection

# Verify backend is selected
./target/release/feagi --config feagi_configuration.toml 2>&1 | grep "Backend selected"

Expected (small genome):

✓ Backend selected: CPU (SIMD)

Expected (large genome):

✓ Backend selected: WGPU (Apple M4 Pro - Metal)

Check 3: GPU Detection

# Check if GPU is available
./target/release/feagi --config feagi_configuration.toml 2>&1 | grep -i "gpu\|metal\|vulkan\|directx"

Step 8: Error Handling

If GPU Not Available

Add to feagi-burst-engine/src/backend/mod.rs (in create_backend):

pub fn create_backend(
backend_type: BackendType,
neuron_capacity: usize,
synapse_capacity: usize,
config: &BackendConfig,
) -> Result<Box<dyn ComputeBackend>> {
let actual_type = if backend_type == BackendType::Auto {
let decision = select_backend(neuron_capacity, synapse_capacity, config);
info!(
"🎯 Backend auto-selection: {} ({})",
decision.backend_type, decision.reason
);
if decision.estimated_speedup > 1.0 {
info!(" Estimated speedup: {:.1}x", decision.estimated_speedup);
}
decision.backend_type
} else {
backend_type
};

match actual_type {
BackendType::CPU => {
info!("🖥️ Using CPU backend (SIMD optimized)");
Ok(Box::new(CPUBackend::new()))
}
#[cfg(feature = "gpu")]
BackendType::WGPU => {
info!("🎮 Using WGPU backend (GPU accelerated)");
match WGPUBackend::new(neuron_capacity, synapse_capacity) {
Ok(backend) => Ok(Box::new(backend)),
Err(e) => {
warn!("⚠️ Failed to create GPU backend: {}", e);
warn!(" Falling back to CPU backend");
Ok(Box::new(CPUBackend::new()))
}
}
}
BackendType::Auto => {
// Should not reach here, but fallback to CPU
Ok(Box::new(CPUBackend::new()))
}
}
}

Step 9: Documentation Updates

Update README.md in feagi/:

Add GPU section:

## GPU Acceleration

FEAGI supports automatic GPU acceleration via WGPU (Metal/Vulkan/DirectX 12).

### Configuration

Edit `feagi_configuration.toml`:

```toml
[neural.hybrid]
enabled = true # Enable GPU auto-selection
gpu_threshold = 1000000 # Use GPU for genomes ≥1M synapses

[resources]
use_gpu = true # Enable GPU globally
gpu_memory_fraction = 0.8 # Use 80% of GPU memory

Building with GPU Support

# Default (GPU enabled)
cargo build --release

# CPU only (smaller binary)
cargo build --release --no-default-features

Verification

Check logs on startup:

🎮 Creating NPU with backend: Auto
GPU enabled: true
✓ Backend selected: WGPU (Apple M4 Pro - Metal)

Troubleshooting

GPU not detected: Check drivers (Metal on macOS, Vulkan on Linux, DX12 on Windows)

Performance worse than CPU: Genome too small, increase threshold or disable GPU


---

## Implementation Checklist

- [ ] Step 1: Create `GpuConfig` struct
- [ ] Step 2: Update `RustNPU::new()` signature
- [ ] Step 3: Wire config in `feagi/src/main.rs`
- [ ] Step 4: Update `feagi-inference-engine`
- [ ] Step 5: Test all scenarios
- [ ] Step 6: Update Cargo.toml features
- [ ] Step 7: Run verification checks
- [ ] Step 8: Add error handling
- [ ] Step 9: Update documentation

**Estimated Time**: 1-2 weeks (5-10 days)

**Team Size**: 1 engineer

**Complexity**: Low (straightforward integration)

---

## Commit Messages

commit 1: Add GpuConfig struct to burst engine backend commit 2: Update RustNPU to accept GPU configuration commit 3: Wire GPU config from TOML to NPU in main binary commit 4: Update feagi-inference-engine with GPU support commit 5: Add comprehensive GPU config tests commit 6: Update Cargo.toml with GPU feature flags commit 7: Add error handling for GPU initialization failures commit 8: Update documentation with GPU configuration guide


---

**Next Steps**: See verification script in `GPU_VERIFICATION_SCRIPT.md`