Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MPI Standalone Implementation - First Bits #46

Merged
merged 27 commits into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7a0a305
adding helloworld example code
csegarragonz Dec 15, 2020
cd2c581
skeleton of native mpi compilation
csegarragonz Dec 17, 2020
a4f6867
adding a task to run mpi-specific applications
csegarragonz Dec 17, 2020
feb7e8e
adding executor script
csegarragonz Dec 18, 2020
6e97ea2
adding new faabric mpi main macro
csegarragonz Jan 4, 2021
0d17cd6
adding scale-up and scale-down options through docker-compose and exp…
csegarragonz Jan 8, 2021
732afe4
adding native mpi_executor in lieu of the overly complex macro
csegarragonz Jan 11, 2021
5ae234d
adding a different target for the native mpi build, and renamed for d…
csegarragonz Jan 11, 2021
0e3bd08
updates to the executor to support being linked as a dynamic library
csegarragonz Jan 13, 2021
b70c9d8
added option to run endpoint thread in background
csegarragonz Jan 13, 2021
37919c0
helloworld working fine with one process
csegarragonz Jan 13, 2021
b2e2b71
helloworld working with >1 processes
csegarragonz Jan 14, 2021
c22aa51
finished automation for deployment and cleanup of MPI tasks
csegarragonz Jan 15, 2021
6f965c9
updating the docs
csegarragonz Jan 15, 2021
7534a0d
fixes
csegarragonz Jan 15, 2021
448c1f3
gracefuly exit
csegarragonz Jan 15, 2021
38cd510
adding build in test file
csegarragonz Jan 15, 2021
8622705
fixes
csegarragonz Jan 15, 2021
a7aa748
adding checks in dev commands
csegarragonz Jan 15, 2021
6f0afcd
addiing link directory as cmake would find pistache
csegarragonz Jan 15, 2021
1f6e8a3
changes suggested in pr comments
csegarragonz Jan 18, 2021
4efc512
switched deployment method to use custom docker compose file and dock…
csegarragonz Jan 18, 2021
35f3447
reverting changes in endpoint, and update the docs
csegarragonz Jan 19, 2021
2bd711f
moving to top-level directory to encapsulate things
csegarragonz Jan 19, 2021
1ecd8f4
modified cmake and added new check in actions
csegarragonz Jan 20, 2021
ca25dad
building container each new release
csegarragonz Jan 20, 2021
027af25
tiny typo
csegarragonz Jan 21, 2021
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
8 changes: 8 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ jobs:
context: .
tags: faasm/faabric:${{ env.TAG_VERSION }}
build-args: FAABRIC_VERSION=${{ env.TAG_VERSION }}
- name: "Build native MPI container"
uses: docker/build-push-action@v2
with:
push: true
file: docker/faabric-mpi-native.dockerfile
context: .
tags: faasm/faabric-mpi-native:${{ env.TAG_VERSION }}
build-args: FAABRIC_VERSION=${{ env.TAG_VERSION }}
24 changes: 24 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,31 @@ jobs:
run: inv dev.cc faabric --shared
- name: "Install Faabric shared library"
run: inv dev.install faabric --shared
- name: "Build MPI native library"
run: inv dev.cc faabricmpi_native --shared
- name: "Install MPI native library"
run: inv dev.install faabricmpi_native --shared
- name: "Build examples"
run: inv examples
- name: "Run example to check"
run: inv examples.execute check

mpi_native:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
env:
HOST_TYPE: ci
REDIS_QUEUE_HOST: redis
REDIS_STATE_HOST: redis
services:
redis:
image: redis
steps:
# --- Code update ---
- name: "Fetch ref"
uses: actions/checkout@v2
# --- Examples ---
- name: "Build docker compose images"
run: ./mpi-native/build.sh
- name: "Run a sample example"
run: ./mpi-native/run.sh
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ endfunction()
add_subdirectory(src/endpoint)
add_subdirectory(src/executor)
add_subdirectory(src/mpi)
add_subdirectory(src/mpi_native)
add_subdirectory(src/proto)
add_subdirectory(src/redis)
add_subdirectory(src/scheduler)
Expand All @@ -82,7 +83,7 @@ add_library(faabric
$<TARGET_OBJECTS:util_obj>
)

add_dependencies(faabric pistache_ext spdlog_ext)
add_dependencies(faabric pistache spdlog_ext)

target_link_libraries(faabric
${Protobuf_LIBRARIES}
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,9 @@ inv container.push
inv container.build --push
```

## Additional documentation

More detail on some key features and implementations can be found below:

- [Native MPI builds](docs/native_mpi.md) - run native applications against
Faabric's MPI library.
8 changes: 7 additions & 1 deletion cmake/ExternalProjects.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ set(GRPC_PLUGIN /usr/local/bin/grpc_cpp_plugin)

# Pistache
ExternalProject_Add(pistache_ext
GIT_REPOSITORY "https://github.com/oktal/pistache.git"
GIT_REPOSITORY "https://github.com/pistacheio/pistache.git"
GIT_TAG "2ef937c434810858e05d446e97acbdd6cc1a5a36"
CMAKE_CACHE_ARGS "-DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX}"
BUILD_BYPRODUCTS ${CMAKE_INSTALL_PREFIX}/lib/libpistache.so
)
ExternalProject_Get_Property(pistache_ext SOURCE_DIR)
set(PISTACHE_INCLUDE_DIR ${SOURCE_DIR}/include)
add_library(pistache SHARED IMPORTED)
add_dependencies(pistache pistache_ext)
set_target_properties(pistache
PROPERTIES IMPORTED_LOCATION ${CMAKE_INSTALL_PREFIX}/lib/libpistache.so
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this looks relatively clean. Can you move faasm and faasm-toolchain to this version of Faabric to check they both still work after (or before) merging this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is faasm's and here the toolchain's. Should we merge those PRs?

Note that the toolchain one would not pass for some missmatch in the submodule build (which I am looking into) but afaik everything else worked fine (as to what this PR is concerned).


# RapidJSON
ExternalProject_Add(rapidjson_ext
Expand Down
29 changes: 29 additions & 0 deletions docker/faabric-mpi-native.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM faasm/grpc-root:0.0.16
ARG FAABRIC_VERSION

# Note - the version of grpc-root here can be quite behind as it's rebuilt very
# rarely

# Redis
RUN apt install -y \
libpython3-dev \
python3-dev \
python3-pip \
python3-venv \
redis-tools

# Put the code in place
WORKDIR /code
RUN git clone -b v${FAABRIC_VERSION} https://github.com/faasm/faabric

WORKDIR /code/faabric

RUN pip3 install invoke

# Build MPI native lib
RUN inv dev.cmake --shared
RUN inv dev.cc faabricmpi_native --shared
RUN inv dev.install faabricmpi_native --shared

# Build examples
RUN inv examples.build
20 changes: 20 additions & 0 deletions docs/native_mpi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Native MPI execution in Faabric

Faabric supports linking MPI binaries against our custom MPI implementation
used in [Faasm](https://github.com/faasm/faasm). This way, you can test the
compliance of your MPI application with our API (a subset of the standard)
without the burden of cross-compiling to WebAssembly.

To run native MPI applications you need to first modify your binary matching
the examples provided, and then build the worker image running:
```
inv container.build-mpi-native
csegarragonz marked this conversation as resolved.
Show resolved Hide resolved
```

Then you may run arbitrary deployments setting the right values in
`mpi-native/mpi-native.env` and running `./mpi-native/run.sh`.

You may remove all stopped and running container images with:
```bash
./mpi-native/clean.sh
```
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function(add_example example_name)
target_link_libraries(${example_name}
faabric
faabricmpi
faabricmpi_native
protobuf
pthread
pistache
Expand All @@ -31,6 +32,7 @@ function(add_example example_name)
endfunction()

add_example(check)
add_example(mpi_helloworld)
add_example(server)

add_custom_target(all_examples DEPENDS ${ALL_EXAMPLES})
62 changes: 62 additions & 0 deletions examples/mpi_helloworld.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <faabric/util/logging.h>

#include <faabric/mpi-native/MpiExecutor.h>
#include <faabric/mpi/mpi.h>

int main(int argc, char** argv)
csegarragonz marked this conversation as resolved.
Show resolved Hide resolved
{
auto logger = faabric::util::getLogger();
auto& scheduler = faabric::scheduler::getScheduler();
auto& conf = faabric::util::getSystemConfig();

// Global configuration
conf.maxNodes = 1;
conf.maxNodesPerFunction = 1;

bool __isRoot;
int __worldSize;
if (argc < 2) {
logger->debug("Non-root process started");
__isRoot = false;
} else if (argc < 3) {
logger->error("Root process started without specifying world size!");
return 1;
} else {
logger->debug("Root process started");
__worldSize = std::stoi(argv[2]);
__isRoot = true;
logger->debug("MPI World Size: {}", __worldSize);
}

// Pre-load message to bootstrap execution
if (__isRoot) {
faabric::Message msg = faabric::util::messageFactory("mpi", "exec");
msg.set_mpiworldsize(__worldSize);
scheduler.callFunction(msg);
}

{
faabric::executor::SingletonPool p;
p.startPool();
}

return 0;
}

int faabric::executor::mpiFunc()
{
auto logger = faabric::util::getLogger();
logger->info("Hello world from Faabric MPI Main!");

MPI_Init(NULL, NULL);

int rank, worldSize;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

logger->info("Hello faabric from process {} of {}", rank + 1, worldSize);

MPI_Finalize();

return 0;
}
2 changes: 2 additions & 0 deletions include/faabric/executor/FaabricExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class FaabricExecutor
bool success,
const std::string& errorMsg);

virtual void postFinishCall();

virtual void postFinish();

bool _isBound = false;
Expand Down
10 changes: 9 additions & 1 deletion include/faabric/executor/FaabricPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class FaabricPool

void startFunctionCallServer();

void startThreadPool();
void startThreadPool(bool background = true);

void startStateServer();

Expand Down Expand Up @@ -42,6 +42,14 @@ class FaabricPool
std::thread poolThread;
std::vector<std::thread> poolThreads;
};

class ExecutorPoolFinishedException : public faabric::util::FaabricException
{
public:
explicit ExecutorPoolFinishedException(std::string message)
: FaabricException(std::move(message))
{}
};
}

// Macro for quickly defining functions
Expand Down
44 changes: 44 additions & 0 deletions include/faabric/mpi-native/MpiExecutor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <faabric/endpoint/FaabricEndpoint.h>
#include <faabric/executor/FaabricExecutor.h>
#include <faabric/executor/FaabricPool.h>
#include <faabric/scheduler/Scheduler.h>
#include <faabric/util/logging.h>

namespace faabric::executor {
class MpiExecutor final : public faabric::executor::FaabricExecutor
{
public:
explicit MpiExecutor();

bool doExecute(faabric::Message& msg) override;

void postFinishCall() override;

void postFinish() override;
};

class SingletonPool : public faabric::executor::FaabricPool
{
public:
SingletonPool();

~SingletonPool();

void startPool();

protected:
std::unique_ptr<FaabricExecutor> createExecutor(int threadIdx) override
{
return std::make_unique<MpiExecutor>();
}

private:
faabric::endpoint::FaabricEndpoint endpoint;
faabric::scheduler::Scheduler& scheduler;
};

extern faabric::Message* executingCall;
extern int __attribute__((weak)) mpiFunc();
}
17 changes: 17 additions & 0 deletions mpi-native/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

set -e

THIS_DIR=$(dirname $(readlink -f $0))
PROJ_ROOT=${THIS_DIR}/..

pushd ${PROJ_ROOT} >> /dev/null

source ./mpi-native/mpi-native.env

docker-compose \
--file ${COMPOSE_FILE} \
--env-file ${ENV_FILE} \
build

popd >> /dev/null
17 changes: 17 additions & 0 deletions mpi-native/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

set -e

THIS_DIR=$(dirname $(readlink -f $0))
PROJ_ROOT=${THIS_DIR}/..

pushd ${PROJ_ROOT} >> /dev/null

source ./mpi-native/mpi-native.env

docker-compose \
--file ${COMPOSE_FILE} \
--env-file ${ENV_FILE} \
down

popd >> /dev/null
34 changes: 34 additions & 0 deletions mpi-native/mpi-native-docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: "3"

services:
redis:
image: redis

worker:
image: ${FAABRIC_MPI_NATIVE_IMAGE}
entrypoint: /code/faabric/examples/build/${MPI_EXAMPLE}
working_dir: /code/faabric
privileged: true
environment:
- LD_LIBRARY_PATH=/usr/local/lib:/build/faabric/install/lib
- FUNCTION_STORAGE=local
- LOG_LEVEL=debug
- REDIS_STATE_HOST=redis
- REDIS_QUEUE_HOST=redis
depends_on:
- redis

master:
image: ${FAABRIC_MPI_NATIVE_IMAGE}
entrypoint: ['/code/faabric/examples/build/${MPI_EXAMPLE}', 'master', '${MPI_WORLD_SIZE}']
working_dir: /code/faabric
privileged: true
environment:
- LD_LIBRARY_PATH=/usr/local/lib:/build/faabric/install/lib
- FUNCTION_STORAGE=local
- LOG_LEVEL=debug
- REDIS_STATE_HOST=redis
- REDIS_QUEUE_HOST=redis
depends_on:
- redis
- worker
10 changes: 10 additions & 0 deletions mpi-native/mpi-native.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FAABRIC_VERSION=0.0.16
FAABRIC_MPI_NATIVE_IMAGE=faasm/faabric-mpi-native:0.0.16
COMPOSE_PROJECT_NAME=faabric-mpi

COMPOSE_FILE="./mpi-native/mpi-native-docker-compose.yml"
ENV_FILE="./mpi-native/mpi-native.env"

# Deployment-specific
MPI_WORLD_SIZE=3
MPI_EXAMPLE=mpi_helloworld
Loading