Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions INSTALL_STEPS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# PaRSEC Installation Instructions

## Prerequisites
Ensure the following dependencies are installed:
```bash
sudo apt-get update
sudo apt-get install -y libopenmpi-dev openmpi-bin cmake bison libhwloc-dev
```

## Building PaRSEC
1. Create a build directory and enter it:
```bash
mkdir builddir && cd builddir
```

2. Run the configure script. Note that we disable the MPI+HWLOC compatibility check to avoid potential conflicts with system-installed libraries:
```bash
../configure --with-mpi --without-hwloc --disable-debug --prefix=$PWD/install -DMPI_HWLOC_COMPAT_CHECK=OFF
```

3. Build and install:
```bash
make install
```

The binaries and libraries will be available in `builddir/install`.
34 changes: 34 additions & 0 deletions parsec-agent-project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# PaRSEC-Agent Research Framework

This project implements a research framework for mapping AI agents onto the PaRSEC (Parallel Robust Scalable Applications) runtime. It follows a 7-step implementation journey to build a distributed, asynchronous, and parallel agentic system.

## Project Structure
- **step1/**: Build verification and PaRSEC initialization.
- **step2/**: Introduction to Dynamic Task Discovery (DTD).
- **step3/**: Implementation of recursive task insertion for agentic loops.
- **step4/**: Design of the ReAct state machine using tasks.
- **step5/**: Integration with Ollama for real LLM reasoning.
- **step6/**: Implementation of the Asynchronous I/O bridge to prevent core stalling.
- **step7/**: Execution of N parallel agents across multiple CPU cores.

## Prerequisites
- PaRSEC (installed at `$HOME/parsec/builddir/install`)
- OpenMPI
- libcurl
- Ollama (running with the `tinyllama` model)

## Global Build Instructions
Each step is a standalone CMake project. To build any step:
```bash
cd stepX
mkdir build && cd build
cmake ..
make
```

## Running
Ensure your `LD_LIBRARY_PATH` includes the PaRSEC library path:
```bash
export LD_LIBRARY_PATH=$HOME/parsec/builddir/install/lib:$LD_LIBRARY_PATH
```
Then run the specific executable for each step using `mpirun`.
13 changes: 13 additions & 0 deletions parsec-agent-project/step1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.21)
project(parsec-agent-step1 C)

# Set the path to your PaRSEC installation
set(PaRSEC_ROOT "$ENV{HOME}/parsec/builddir/install")
list(APPEND CMAKE_PREFIX_PATH "${PaRSEC_ROOT}/share/cmake/parsec")

find_package(PaRSEC REQUIRED)
find_package(MPI REQUIRED)

add_executable(parsec_ok main.c)
target_include_directories(parsec_ok PRIVATE "${PaRSEC_ROOT}/include" ${MPI_C_INCLUDE_DIRS})
target_link_libraries(parsec_ok "${PaRSEC_ROOT}/lib/libparsec.so" ${MPI_C_LIBRARIES})
15 changes: 15 additions & 0 deletions parsec-agent-project/step1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# PaRSEC-Agent: Step 1 - Build Verification

## Purpose
The goal of this step is to verify that the PaRSEC installation is correct and that the build system (CMake) can correctly link against PaRSEC and MPI.

## Key Concepts
- **parsec_init**: Initializes the PaRSEC runtime environment.
- **parsec_fini**: Safely shuts down the PaRSEC context.
- **MPI_Init_thread**: Required because PaRSEC is a multi-threaded runtime and needs MPI to support the `MPI_THREAD_MULTIPLE` level.

## How to Build and Run
1. Enter the build directory: `mkdir build && cd build`
2. Configure: `cmake ..`
3. Build: `make`
4. Run: `LD_LIBRARY_PATH=$HOME/parsec/builddir/install/lib:$LD_LIBRARY_PATH mpirun -n 1 ./parsec_ok`
25 changes: 25 additions & 0 deletions parsec-agent-project/step1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdio.h>
#include <mpi.h>
#include <parsec.h>

int main(int argc, char **argv) {
parsec_context_t* parsec_context;
int parsec_argc = argc;
char** parsec_argv = argv;
int provided;

MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);

parsec_context = parsec_init(-1, &parsec_argc, &parsec_argv);
if(NULL == parsec_context) {
fprintf(stderr, "parsec_init failed\n");
MPI_Finalize();
return -1;
}

printf("PaRSEC OK\n");

parsec_fini(&parsec_context);
MPI_Finalize();
return 0;
}
12 changes: 12 additions & 0 deletions parsec-agent-project/step2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.21)
project(parsec-agent-step2 C)

set(PaRSEC_ROOT "$ENV{HOME}/parsec/builddir/install")
list(APPEND CMAKE_PREFIX_PATH "${PaRSEC_ROOT}/share/cmake/parsec")

find_package(PaRSEC REQUIRED)
find_package(MPI REQUIRED)

add_executable(dtd_hello main.c)
target_include_directories(dtd_hello PRIVATE "${PaRSEC_ROOT}/include" ${MPI_C_INCLUDE_DIRS})
target_link_libraries(dtd_hello "${PaRSEC_ROOT}/lib/libparsec.so" ${MPI_C_LIBRARIES})
17 changes: 17 additions & 0 deletions parsec-agent-project/step2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# PaRSEC-Agent: Step 2 - DTD Basics

## Purpose
This step introduces Dynamic Task Discovery (DTD) in PaRSEC. It demonstrates how to define a task class and insert independent tasks into a taskpool.

## Key Concepts
- **parsec_dtd_taskpool_new**: Creates a new taskpool dedicated to DTD.
- **parsec_dtd_create_task_class**: Defines the signature of a task (number of arguments and their types).
- **PARSEC_VALUE**: Indicates that an argument should be passed by value (copied into the task).
- **parsec_dtd_unpack_args**: Extracts the arguments from the task structure inside the task body.
- **PARSEC_DTD_ARG_END**: Sentinel value used to terminate variadic argument lists.

## How to Build and Run
1. Enter the build directory: `mkdir build && cd build`
2. Configure: `cmake ..`
3. Build: `make`
4. Run: `LD_LIBRARY_PATH=$HOME/parsec/builddir/install/lib:$LD_LIBRARY_PATH mpirun -n 1 ./dtd_hello`
59 changes: 59 additions & 0 deletions parsec-agent-project/step2/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <stdio.h>
#include <mpi.h>
#include <parsec.h>
#include <parsec/interfaces/dtd/insert_function.h>
#include <parsec/mca/device/device.h>

static int dtd_hello_body(parsec_execution_stream_t *es, parsec_task_t *task)
{
int index;
int value;

parsec_dtd_unpack_args(task, &index, &value);

printf("Task index %d received value %d\n", index, value);

return PARSEC_HOOK_RETURN_DONE;
}

int main(int argc, char **argv)
{
int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);

parsec_context_t *parsec_context = parsec_init(-1, NULL, NULL);
if(NULL == parsec_context) {
MPI_Finalize();
return -1;
}

parsec_taskpool_t *tp = parsec_dtd_taskpool_new();

parsec_dtd_create_task_class(tp, "hello_task",
sizeof(int), PARSEC_VALUE,
sizeof(int), PARSEC_VALUE,
PARSEC_DTD_ARG_END,
dtd_hello_body,
0);

parsec_context_add_taskpool(parsec_context, tp);
parsec_context_start(parsec_context);

for(int i = 0; i < 4; i++) {
int val = i * 10;
// DTD insert task takes function pointer, priority, and device_type
parsec_dtd_insert_task(tp, dtd_hello_body, 0,
PARSEC_DEV_CPU,
"hello_task",
sizeof(int), &i, PARSEC_VALUE,
sizeof(int), &val, PARSEC_VALUE,
PARSEC_DTD_ARG_END);
}

parsec_taskpool_wait(tp);
parsec_taskpool_free(tp);

parsec_fini(&parsec_context);
MPI_Finalize();
return 0;
}
12 changes: 12 additions & 0 deletions parsec-agent-project/step3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.21)
project(parsec-agent-step3 C)

set(PaRSEC_ROOT "$ENV{HOME}/parsec/builddir/install")
list(APPEND CMAKE_PREFIX_PATH "${PaRSEC_ROOT}/share/cmake/parsec")

find_package(PaRSEC REQUIRED)
find_package(MPI REQUIRED)

add_executable(dtd_loop main.c)
target_include_directories(dtd_loop PRIVATE "${PaRSEC_ROOT}/include" ${MPI_C_INCLUDE_DIRS})
target_link_libraries(dtd_loop "${PaRSEC_ROOT}/lib/libparsec.so" ${MPI_C_LIBRARIES})
15 changes: 15 additions & 0 deletions parsec-agent-project/step3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# PaRSEC-Agent: Step 3 - Recursive Task Insertion

## Purpose
This step demonstrates the core primitive for an agentic loop: the ability for a task to insert its successor while it is executing.

## Key Concepts
- **parsec_dtd_get_taskpool**: Used inside a task body to retrieve the handle to the taskpool so new tasks can be inserted.
- **Recursive insertion**: Task N calls `parsec_dtd_insert_task` for Task N+1 before completing.
- **Thread Safety**: PaRSEC ensures that inserting tasks from within other tasks is thread-safe across all worker cores.

## How to Build and Run
1. Enter the build directory: `mkdir build && cd build`
2. Configure: `cmake ..`
3. Build: `make`
4. Run: `LD_LIBRARY_PATH=$HOME/parsec/builddir/install/lib:$LD_LIBRARY_PATH mpirun -n 1 ./dtd_loop`
71 changes: 71 additions & 0 deletions parsec-agent-project/step3/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <stdio.h>
#include <mpi.h>
#include <parsec.h>
#include <parsec/interfaces/dtd/insert_function.h>
#include <parsec/mca/device/device.h>

#define MAX_TASKS 5

// Forward declaration of the task body
static int dtd_loop_body(parsec_execution_stream_t *es, parsec_task_t *task);

int main(int argc, char **argv)
{
int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);

parsec_context_t *parsec_context = parsec_init(-1, NULL, NULL);
if(NULL == parsec_context) {
MPI_Finalize();
return -1;
}

parsec_taskpool_t *tp = parsec_dtd_taskpool_new();

// Define task class
parsec_dtd_create_task_class(tp, "loop_task",
sizeof(int), PARSEC_VALUE,
PARSEC_DTD_ARG_END,
dtd_loop_body,
0);

parsec_context_add_taskpool(parsec_context, tp);
parsec_context_start(parsec_context);

// Start the loop with task 0
int first_task = 0;
parsec_dtd_insert_task(tp, dtd_loop_body, 0,
PARSEC_DEV_CPU,
"loop_task",
sizeof(int), &first_task, PARSEC_VALUE,
PARSEC_DTD_ARG_END);

parsec_taskpool_wait(tp);
parsec_taskpool_free(tp);

parsec_fini(&parsec_context);
MPI_Finalize();
return 0;
}

static int dtd_loop_body(parsec_execution_stream_t *es, parsec_task_t *task)
{
int current_idx;
parsec_dtd_unpack_args(task, &current_idx);

printf("Task N=%d executing\n", current_idx);

if (current_idx < MAX_TASKS - 1) {
int next_idx = current_idx + 1;
printf("Task N=%d inserting Task N=%d\n", current_idx, next_idx);

// Use parsec_dtd_get_taskpool(task) to get the taskpool
parsec_dtd_insert_task(parsec_dtd_get_taskpool(task), dtd_loop_body, 0,
PARSEC_DEV_CPU,
"loop_task",
sizeof(int), &next_idx, PARSEC_VALUE,
PARSEC_DTD_ARG_END);
}

return PARSEC_HOOK_RETURN_DONE;
}
12 changes: 12 additions & 0 deletions parsec-agent-project/step4/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.21)
project(parsec-agent-step4 C)

set(PaRSEC_ROOT "$ENV{HOME}/parsec/builddir/install")
list(APPEND CMAKE_PREFIX_PATH "${PaRSEC_ROOT}/share/cmake/parsec")

find_package(PaRSEC REQUIRED)
find_package(MPI REQUIRED)

add_executable(dtd_agent main.c)
target_include_directories(dtd_agent PRIVATE "${PaRSEC_ROOT}/include" ${MPI_C_INCLUDE_DIRS})
target_link_libraries(dtd_agent "${PaRSEC_ROOT}/lib/libparsec.so" ${MPI_C_LIBRARIES})
16 changes: 16 additions & 0 deletions parsec-agent-project/step4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# PaRSEC-Agent: Step 4 - Single Synchronous Agent Loop

## Purpose
This step implements the ReAct (Reason + Act) loop logic. It uses a state object (`agent_state_t`) that is passed between tasks to maintain progress.

## Key Concepts
- **agent_state_t**: A heap-allocated structure containing the agent's memory (thoughts, actions, and step count).
- **think_task**: Analyzes current state and decides on a tool or a final answer.
- **tool_task**: Executes a tool (stubbed) and returns control to the thinking phase.
- **finish_task**: Finalizes the agent run and frees resources.

## How to Build and Run
1. Enter the build directory: `mkdir build && cd build`
2. Configure: `cmake ..`
3. Build: `make`
4. Run: `LD_LIBRARY_PATH=$HOME/parsec/builddir/install/lib:$LD_LIBRARY_PATH mpirun -n 1 ./dtd_agent`
Loading