Quick Start#
This document provides a minimum example to create a simulation project using MASS CUDA and execute it on a single machine.
Step 1: Create a CMake project#
Create a directory for your project with the following structure:
simulation/
├── src/
│ ├── main.cu
│ └── MyPlace.h
└── CMakeLists.txt
In CMakeLists.txt, add the following content to set up the project and link with MASS CUDA:
cmake_minimum_required(VERSION 3.20)
project(simulation LANGUAGES C CXX CUDA)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(MASS_CUDA_REPO_URL "https://bitbucket.org/mass_library_developers/mass_cuda_core")
set(MASS_CUDA_VERSION "feature/multi-gpus-multi-hosts")
include(FetchContent)
FetchContent_Declare(
mass_cuda
GIT_REPOSITORY ${MASS_CUDA_REPO_URL}
GIT_TAG ${MASS_CUDA_VERSION}
)
FetchContent_MakeAvailable(mass_cuda)
add_executable(simulation
src/main.cu
src/MyPlace.cu
)
target_include_directories(simulation PRIVATE src)
target_link_libraries(simulation PRIVATE mass_cuda)
set_target_properties(simulation PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
Step 2: Implement your simulation#
In MyPlace.h, define your custom behavior for each place instance. You can separate the implementation into a additional .cu file if needed, but we use header-only style here for simplicity.
#pragma once
#include <mass/Place.h>
class MyPlace : public mass::Place {
public:
__universal__ explicit MyPlace(const mass::Index localIndex) : mass::Place(localIndex) {}
enum ATTRIBUTE {
ATTR
}
enum FUNCTION {
FUNC
}
__device__ void callMethod(const mass::FunctionId funcId, void*const arg) override {
switch (funcId) {
case FUNC:
func(*static_cast<const int*>(arg));
break;
default:
break;
}
}
__device__ void func(const int arg) {
const auto attrPtr = getAttribute<int>(ATTR);
*attrPtr += arg;
}
};
Then in main.cu, set up the simulation and define the execution loop.
#include <mass/Mass.h>
#include <iostream>
#include "MyPlace.h"
int main() {
constexpr int numDevices = 2; // set it to the number of GPUs you have
constexpr int size = 100;
mass::Mass::init();
MASS_SCOPE_DEFER() { mass::Mass::finish(); };
const auto places = mass::Mass::createPlaces<MyPlace>(0, {
.size = { size, size },
.ghostSize = 0
});
places->setAttribute<int>(MyPlace::ATTRIBUTE::ATTR, 1, 0);
places->finalizeAttributes();
for (auto step = 0; step < 1000; ++step) {
places->callAll(MyPlace::FUNCTION::FUNC, 2);
}
const auto attr = places->downloadAttributes<int>(MyPlace::ATTRIBUTE::ATTR);
for (auto deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex) {
for (auto i = 0; i < size * size / numDevices; ++i) {
std::cout << attr[deviceIndex][i] << " ";
}
std::cout << std::endl;
}
return 0;
}
Step 3: Build and run#
To build the project, run the following commands in the terminal:
mkdir build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
After that, the binary executable will be in the build directory. You can run it with:
./build/simulation