Skip to content

NickSpyker/multi-agent-engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Multi-Agent Engine

A concurrent Rust library for building multi-agent systems with lock-free CPU/GPU hybrid execution.

Overview

multi-agent-engine is a library designed for building applications based on multi-agent systems (MAS), agent-based models (ABM), and agent-oriented programming (AOP) paradigms. It provides a ready-to-use pipeline and tooling for generic use cases, with native support for multithreaded CPU execution and GPU acceleration.

While the engine excels at simulations, its architecture is general-purpose and can power any application requiring concurrent processing with responsive user interaction: games, real-time data pipelines, robotics controllers, and more.

Core Architecture

The engine follows a multi-thread architecture that separates system logic from user interaction, enabling independent operation at different frequencies while maintaining efficient data synchronization.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           Multi-Agent Engine                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Controller A     β”‚  β”‚ Controller B     β”‚  ...  β”‚ Controller N     β”‚  β”‚
β”‚  β”‚ Thread (60 Hz)   β”‚  β”‚ Thread (30 Hz)   β”‚       β”‚ Thread (10 Hz)   β”‚  β”‚
β”‚  β”‚                  β”‚  β”‚                  β”‚       β”‚                  β”‚  β”‚
β”‚  β”‚ - User Input     β”‚  β”‚ - Logging        β”‚       β”‚ - Network I/O    β”‚  β”‚
β”‚  β”‚ - Rendering      β”‚  β”‚ - Metrics        β”‚       β”‚ - Remote Control β”‚  β”‚
β”‚  β”‚ - UI Logic       β”‚  β”‚ - Recording      β”‚       β”‚ - Sync           β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚           β”‚                     β”‚                          β”‚            β”‚
β”‚           β–Ό                     β–Ό                          β–Ό            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                        Config Channels (ArcSwap)                  β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚  β”‚
β”‚  β”‚  β”‚ Config A  β”‚       β”‚ Config B  β”‚    ...     β”‚ Config N  β”‚       β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚  β”‚
β”‚  β”‚            Controllers β†’ System (independent configs)             β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                    β”‚                                    β”‚
β”‚                                    β–Ό                                    β”‚
β”‚                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚
β”‚                         β”‚  System Thread   β”‚                            β”‚
β”‚                         β”‚   (e.g., 30 Hz)  β”‚                            β”‚
β”‚                         β”‚                  β”‚                            β”‚
β”‚                         β”‚  - Agent Logic   β”‚                            β”‚
β”‚                         β”‚  - Physics       β”‚                            β”‚
β”‚                         β”‚  - Processing    β”‚                            β”‚
β”‚                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                            β”‚
β”‚                                  β”‚                                      β”‚
β”‚                                  β–Ό                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                         State (ArcSwap)                           β”‚  β”‚
β”‚  β”‚                     System β†’ Controllers                          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    Message Queues (per Controller)                β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚  β”‚
β”‚  β”‚  β”‚ Controller A ↔  β”‚  β”‚ Controller B ↔  β”‚  β”‚ Controller N ↔  β”‚    β”‚  β”‚
β”‚  β”‚  β”‚     System      β”‚  β”‚     System      β”‚  β”‚     System      β”‚    β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Thread Hosting Options

By default, the engine spawns dedicated threads for the System and each Controller. However, you can configure the engine to run either the System or one Controller on the engine's main thread. This is useful for:

  • GUI frameworks that require the main thread for rendering.
  • Reducing thread count in resource-constrained environments.
  • Integration with existing event loops.
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Thread Hosting Modes                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

 Mode 1: Default (all separate threads)
 ───────────────────────────────────────
 Engine Thread: idle/management only
 Controller A:  dedicated thread
 Controller B:  dedicated thread
 System:        dedicated thread

 Mode 2: System on engine thread
 ───────────────────────────────────────
 Engine Thread: runs System
 Controller A:  dedicated thread
 Controller B:  dedicated thread

 Mode 3: Controller on engine thread
 ───────────────────────────────────────
 Engine Thread: runs Controller A (e.g., GUI)
 Controller B:  dedicated thread
 System:        dedicated thread

User Interface

Required Trait Implementations

You must implement two core traits to connect with the engine:

1. Controller Trait

Handles user interaction, input processing, and visualization. Each Controller provides its own typed Config to the System.

trait Controller {
    type Config;
    type OutgoingMessage;
    type IncomingMessage;

    fn initialize(&mut self, initial_state: &State);
    fn update(&mut self, state: &State) -> Option<Self::Config>;
    fn handle_messages(&mut self, messages: Vec<Self::IncomingMessage>);
}

2. System Trait

Contains the core processing logic, agent behaviors, and computation. The System can read from multiple independent Configs.

trait System {
    fn initialize(&mut self);
    fn tick(&mut self, configs: &Configs) -> State;
    fn handle_messages(&mut self, messages: Vec<ControllerMessage>);
}

Required Data Structures

Config (per Controller)

Each Controller defines and provides its own configuration type. The System reads these independently.

// Controller A's config
struct InputConfig {
    // e.g., mouse_position, keyboard_state, selected_tool
}

// Controller B's config
struct SimulationConfig {
    // e.g., time_scale, agent_count, environment_params
}

// Controller C's config
struct NetworkConfig {
    // e.g., sync_rate, peer_list, connection_state
}

State

Current system state, shared with all Controllers (System β†’ Controllers).

struct State {
    // User-defined fields
    // e.g., agent_positions, environment_state, statistics
}

Concurrency Model

Thread Independence

The System and all Controllers operate in separate threads that never block each other. This design enables:

  • Asynchronous execution: Each thread runs at its own frequency
  • Responsive UI: Controllers remain responsive even during heavy processing
  • Scalable performance: System can utilize multiple cores independently
  • Modular design: Controllers can be added or removed without affecting others
Timeline Example (2 Controllers + System):
────────────────────────────────────────────────────────────────────────────>

Controller A (60 Hz): |─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─●─
                          β”‚       β”‚       β”‚       β”‚       β”‚       β”‚
Controller B (20 Hz): |───●───────────────●───────────────●───────────────●─
                          β”‚       β”‚       β”‚       β”‚       β”‚       β”‚
System       (30 Hz): |───●───────●───────●───────●───────●───────●───────●─
                          β”‚       β”‚       β”‚       β”‚       β”‚       β”‚
                         tick    tick    tick    tick    tick    tick

● = frame/tick execution

Data Sharing with ArcSwap

Threads share data through lock-free atomic swap (ArcSwap). Each Controller maintains its own Config channel, while all Controllers read from a shared State.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           Data Flow Diagram                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

 Controller A          Controller B          Controller N
 ────────────          ────────────          ────────────
    WRITE                 WRITE                 WRITE
      β”‚                     β”‚                     β”‚
      β–Ό                     β–Ό                     β–Ό
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚ Config A β”‚          β”‚ Config B β”‚          β”‚ Config N β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”‚                     β”‚                     β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
              ArcSwap (per config)
                     β”‚
                     β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚   System    β”‚  ← Reads configs selectively
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
                   WRITE
                     β”‚
                     β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚    State    β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
              ArcSwap (shared)
                     β”‚
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚              β”‚                          β”‚
      β–Ό              β–Ό                          β–Ό
    READ           READ                       READ
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚ Ctrl A   β”‚  β”‚ Ctrl B   β”‚     ...      β”‚ Ctrl N   β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Access Patterns:

Thread Own Config Other Configs State
System N/A Read-only Write-only
Controller A Write-only None Read-only
Controller B Write-only None Read-only
Controller N Write-only None Read-only

This design ensures:

  • βœ… No locks or mutexes needed for state sharing
  • βœ… Zero blocking between threads
  • βœ… Data race freedom through clear ownership
  • βœ… Independent configs per Controller with typed safety

Message Passing

In addition to shared data, threads communicate through typed message queues. Each Controller has its own bidirectional message channel with the System.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Message Communication                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

 Controller A                              System
 ────────────                              ──────
     β”œβ”€β”€β†’ [Outgoing Queue A] ────────────→  handle_messages()
     β”‚     - UserAction                          β”‚
     β”‚     - ToolSelected                        β–Ό
     β”‚     - SpawnRequest                   Process & Execute
     β”‚                                           β”‚
     β”‚                                           β”‚
     ←── [Incoming Queue A] ←─────────────────────
           - SelectionResult                     β”‚
           - ActionFeedback                      β”‚
                                                 β”‚
 Controller B                                    β”‚
 ────────────                                    β”‚
     β”œβ”€β”€β†’ [Outgoing Queue B] ─────────────────────
     β”‚     - StartRecording                      β”‚
     β”‚     - SetMarker                           β”‚
     β”‚                                           β”‚
     ←── [Incoming Queue B] ←─────────────────────
           - RecordingStats                      β”‚
           - FrameCaptured                       β”‚
                                                 β”‚
 Controller N                                    β”‚
 ────────────                                    β”‚
     β”œβ”€β”€β†’ [Outgoing Queue N] ─────────────────────
     β”‚     - SyncRequest                         β”‚
     β”‚     - PeerUpdate                          β”‚
     β”‚                                           β”‚
     ←── [Incoming Queue N] β†β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           - SyncComplete
           - PeerStatus

Example Message Definitions:

// Controller A (UI) β†’ System
enum UIControllerMessage {
    Pause,
    Resume,
    Reset,
    SpawnAgent { position: Vec3, agent_type: AgentType },
    SelectEntity(EntityId),
}

// System β†’ Controller A (UI)
enum UISystemMessage {
    SelectionResult { entity: Option<EntityInfo> },
    AgentSpawned { id: AgentId },
    ActionFeedback { success: bool, message: String },
}

// Controller B (Metrics) β†’ System
enum MetricsControllerMessage {
    RequestSnapshot,
    SetSamplingRate(f32),
}

// System β†’ Controller B (Metrics)
enum MetricsSystemMessage {
    Snapshot { tick: u64, data: SystemStats },
    SamplingRateConfirmed(f32),
}

GPU Acceleration & Multi-Layer Pipeline

Hybrid CPU/GPU Execution

The System supports flexible compute allocation between CPU and GPU, enabling efficient execution of agent behaviors and physics on appropriate hardware.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       Multi-Layer Processing Pipeline        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

 Input State
      β”‚
      β–Ό
 β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
 β”‚ Layer 1 β”‚ ← CPU: Agent Decision Making
 β”‚  (CPU)  β”‚    - Perception processing
 β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    - Behavior selection
      β–Ό output1
 β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
 β”‚ Layer 2 β”‚ ← GPU: Spatial Queries
 β”‚  (GPU)  β”‚    - Neighbor detection
 β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    - Collision detection
      β–Ό output2
 β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
 β”‚ Layer 3 β”‚ ← GPU: Physics Simulation
 β”‚  (GPU)  β”‚    - Force calculations
 β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    - Position updates
      β–Ό output3
 β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
 β”‚ Layer 4 β”‚ ← CPU: Environment Update
 β”‚  (CPU)  β”‚    - Resource distribution
 β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    - Event handling
      β–Ό output4
      β”‚
 Final State

Agent-Level GPU Execution

Each agent's behavior can be individually executed on GPU, enabling:

  • Massive parallelization for homogeneous agent populations
  • Efficient SIMD operations for agent computations
  • Scalability to thousands or millions of agents
Agents: A1, A2, A3, A4, ..., An

 CPU Execution          GPU Execution
 ─────────────          ─────────────

 A1 β†’ compute           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    ↓                   β”‚ A1 A2 A3 A4 ...  β”‚
 A2 β†’ compute     VS    β”‚ β•‘  β•‘  β•‘  β•‘       β”‚
    ↓                   β”‚ Parallel Compute β”‚
 A3 β†’ compute           β”‚ ↓  ↓  ↓  ↓       β”‚
    ↓                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
   ...
 (Sequential)              (Parallel)

Getting Started

Basic Setup (Single Controller)

// 1. Define your data structures
struct MyConfig {
    /* ... */
}
struct MyState {
    /* ... */
}

// 2. Define your message types
enum MyControllerMessage { /* ... */ }
enum MySystemMessage { /* ... */ }

// 3. Implement the required traits
struct MyController {
    /* ... */
}
impl Controller for MyController {
    type Config = MyConfig;
    type OutgoingMessage = MyControllerMessage;
    type IncomingMessage = MySystemMessage;
    // ...
}

struct MySystem {
    /* ... */
}
impl System for MySystem { /* ... */ }

fn main() {
    // 4. Build and run the engine
    let engine = MultiAgentEngine::builder()
        .with_controller(MyController::new())
        .with_system(MySystem::new())
        .build();

    engine.run();
}

Multi-Controller Setup

// Define multiple controllers with different responsibilities
struct RenderController {
    /* ... */
}
struct MetricsController {
    /* ... */
}
struct NetworkController {
    /* ... */
}

// Each with its own Config type
struct RenderConfig {
    /* ... */
}
struct MetricsConfig {
    /* ... */
}
struct NetworkConfig {
    /* ... */
}

fn main() {
    let engine = MultiAgentEngine::builder()
        .with_controller(RenderController::new())
        .with_controller(MetricsController::new())
        .with_controller(NetworkController::new())
        .with_system(MySystem::new())
        .build();

    engine.run();
}

Running on Engine Thread

fn main() {
    // Run the render controller on the main thread (required by some GUI frameworks)
    let engine = MultiAgentEngine::builder()
        .with_controller_on_engine_thread(RenderController::new())
        .with_controller(MetricsController::new())
        .with_system(MySystem::new())
        .build();

    engine.run(); // RenderController runs here, others in spawned threads
}
fn main() {
    // Or run the System on the main thread
    let engine = MultiAgentEngine::builder()
        .with_controller(RenderController::new())
        .with_controller(MetricsController::new())
        .with_system_on_engine_thread(MySystem::new())
        .build();

    engine.run(); // System runs here, Controllers in spawned threads
}

License

See LICENSE-APACHE and LICENSE-MIT for details.

About

A concurrent Rust library for building multi-agent systems with lock-free CPU/GPU hybrid execution.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published