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

#16: Create lbaf-viz interface #60

Merged
merged 58 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
cdb5ff0
#16: bindings: Lay out vizualizer binding structure and build system
pierrepebay Oct 12, 2023
d78a627
#16: bindings: Continue binding setup
pierrepebay Oct 12, 2023
abb6f9c
#16: bindings: Try pip build and PyPI publish from CI
pierrepebay Oct 21, 2023
2d96c45
#16: bindings: Fix publishing target to testPyPI
pierrepebay Oct 21, 2023
230cb0b
#16: bindings: Fix typo
pierrepebay Oct 21, 2023
4868099
#16: bindings: Fix typo
pierrepebay Oct 21, 2023
c5cd288
#16: bindings: Try buidling python package with cibuildwheel
pierrepebay Nov 7, 2023
8679d68
#16: bindings: Fix nanobind include getter
pierrepebay Nov 7, 2023
4af066d
#16: bindings: Fix cpp file name in setup.py
pierrepebay Nov 7, 2023
008e79b
#16: bindings: Specify cmake build in setup.py
pierrepebay Nov 7, 2023
e3accd1
#16: bindings: Continue cmake build backend for setup.py
pierrepebay Nov 7, 2023
c10c422
#16: bindings: complete setup for local pip install of binded vttv pa…
pierrepebay Nov 11, 2023
068bab7
#16: bindings: Specify package in init file
pierrepebay Nov 11, 2023
563b1e9
#16: bindings: Add a bit more functionality to binded function
pierrepebay Nov 11, 2023
5f44dab
#16: bindings: Specify build directory in setup.py
pierrepebay Nov 23, 2023
8527bab
#16: bindings: Switch to modern python package build method and clean…
pierrepebay Nov 23, 2023
f74f58e
#16: bindings: Update README to describe python binding build
pierrepebay Nov 23, 2023
ac5e194
#16: readme: fix subtitle
pierrepebay Nov 23, 2023
6bf84d0
#16: bindings: Add initial python bindings CI testing
pierrepebay Nov 23, 2023
2b3b38f
#16: bindings: Fix testing CI
pierrepebay Nov 23, 2023
c87c921
#16: bindings: Fix pip install directory in CI testing
pierrepebay Nov 23, 2023
694b5a5
#16: bindings: Specify compiler for cmake in CI testing
pierrepebay Nov 23, 2023
11b75b3
#16: bindings: Fix VTK build path in CI testing
pierrepebay Nov 23, 2023
4210bf2
#16: bindings: Fix conda environment initialization before CI testing
pierrepebay Nov 23, 2023
e4ca7fc
#16: bindings: pip install pyyaml for CI testing
pierrepebay Nov 23, 2023
ed1ade0
#16: bindings: Add configuration parsing, begin data parsing
pierrepebay Nov 28, 2023
6f5fa51
#16: bindings: Fix test script
pierrepebay Nov 29, 2023
4611bf5
#16: bindings: Add data parsing and render call
pierrepebay Dec 5, 2023
9e3c62c
#16: bindings: Make json processing concurrent
pierrepebay Dec 16, 2023
1ed9664
#16: bindings: Fix narrowing int to NodeType warning
pierrepebay Dec 19, 2023
0772e7b
#16: bindings: Fix bindings test output directory
pierrepebay Dec 19, 2023
297a5d9
#16: Add missing qoi getters
pierrepebay Jan 30, 2024
32d021c
#16: Start adding different qoi handling
pierrepebay Feb 12, 2024
744065a
#16: fix error message
cwschilly Feb 14, 2024
f4022b0
#16: add vtk_init to all created targets; add load array when not giv…
cwschilly Mar 6, 2024
9a0f77d
#16: fix segfault in python bindings; comment out failing asserts
cwschilly Mar 11, 2024
9b6f8d3
#16: rework QOI getters and fix max volume function
cwschilly Mar 22, 2024
b9ade9d
#16: add id and sentinel_load QOIs
cwschilly Mar 26, 2024
d63b120
#16: Fix communications and object glyph scaling
pierrepebay Apr 4, 2024
887fb05
#16: fix object qoi call
cwschilly Apr 9, 2024
6459c47
#16: Centralize JSON reading with file and string capabilities
pierrepebay Apr 15, 2024
2edb768
#16: Fix and optimize communication normalization, print warning for …
pierrepebay Apr 15, 2024
36751cb
#16: use QOIVariantTypes as qoi getters; convert to double before ren…
cwschilly Apr 16, 2024
02da9f5
#16: add synthetic data with attributes
cwschilly Apr 17, 2024
0b875f1
#16: tmp CI fixes
cwschilly Apr 24, 2024
333fa14
#16: install vtk-osmesa
cwschilly Apr 24, 2024
273b2ea
#16: try different cmake flags in base dockerfile
cwschilly Apr 24, 2024
9adec3f
#16: disable X in base docker image
cwschilly Apr 24, 2024
bad1125
#16: fix osmesa typo and disable other flags explicitly
cwschilly Apr 24, 2024
5e8ec75
#16: apt install libosmesa6-dev
cwschilly Apr 24, 2024
46f3ad5
#16: add rank_id obj qoi and allow for integer categorical qoi
cwschilly Apr 24, 2024
9963d86
#16: disable bindings CI pipeline
pierrepebay Apr 26, 2024
9c7b37e
#16: remove comments, add checks for openmp, fix code formatting
cwschilly May 7, 2024
208ccf8
#16: add ifdef for remaining omp include
cwschilly May 7, 2024
5d82a9a
#16: wrap all omp calls in ifdefs in tv.cc
cwschilly May 7, 2024
512d0da
#16: Improve OpenMP integration
pierrepebay May 7, 2024
31c8200
#16: fixed N_THREADS setting
cwschilly May 7, 2024
0a66707
#16: fix openmp availability check
cwschilly May 7, 2024
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
47 changes: 47 additions & 0 deletions .github/workflows/build-and-test-bindings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Build and Test Bindings Ubuntu 22.04 gcc 11 x64

# Trigger the workflow on push or pull request
on:
# push:
# branches:
# - master
# pull_request:
# types: [opened, reopened, synchronize, converted_to_draft, ready_for_review]

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
env:
OUTPUT_DIR: '/tmp/out'
name: vt-tv bindings build and test
steps:
- uses: actions/checkout@v3

- name: CI Variables
id: vars
run: echo "DOCKER_TAG=$(echo ${{ github.ref }} | cut -d'/' -f3- | sed 's/[^a-z0-9_-]/__/gi')" >> $GITHUB_ENV

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2

- name: Inspect Builder
run: |
echo "Name: ${{ steps.buildx.outputs.name }}"
echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
echo "Status: ${{ steps.buildx.outputs.status }}"
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
echo "DOCKER_TAG: ${{ env.DOCKER_TAG }}"

- name: Build the Docker Image; build and test vt-tv bindings
id: docker_build
uses: docker/build-push-action@v3
with:
push: false
tags: ${{ env.DOCKER_TAG }}
context: .
file: ./ci/build-and-test-bindings.dockerfile
outputs: type=local,dest=${{ env.OUTPUT_DIR }}
57 changes: 15 additions & 42 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,45 @@ set(VT_TV_LIBRARY_NS vt::lib::vt-tv)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# add -fPIC to all targets
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard to use")
endif()
message(STATUS "CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}")

option(vt_tv_python_bindings_enabled "Build vt-tv with Python bindings" ON)
option(vt_tv_openmp_enabled "Build vt-tv with openMP support" ON)
option(VT_TV_PYTHON_BINDINGS_ENABLED "Build vt-tv with Python bindings" ON)
option(VT_TV_OPENMP_ENABLED "Build vt-tv with openMP support" ON)
set(VT_TV_N_THREADS "2" CACHE STRING "Number of OpenMP threads to use")

include(cmake/load_packages.cmake)

if(APPLE)
add_compile_options(-ffat-lto-objects)
endif()

if(openmp_enabled)
set(VT_TV_NUM_THREADS "2" CACHE STRING "Number of threads to use")
add_definitions(-DVT_TV_NUM_THREADS=${VT_TV_NUM_THREADS})
endif()
add_definitions(-DVT_TV_N_THREADS=${VT_TV_N_THREADS})
add_definitions(-DVT_TV_OPENMP_ENABLED=${VT_TV_OPENMP_ENABLED})

add_custom_target(vt_tv_examples)
add_custom_target(vt_tv_tests)
add_custom_target(vt_tv_apps)

set(PROJECT_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(PROJECT_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(PROJECT_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib)
set(PROJECT_EXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
set(PROJECT_APP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/apps)
set(PROJECT_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(PROJECT_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(PROJECT_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib)
set(PROJECT_EXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
set(PROJECT_APP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/apps)
set(PROJECT_BINDINGS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bindings)

include(CTest)

add_subdirectory(src)
add_subdirectory(examples)
add_subdirectory(tests)
add_subdirectory(apps)
add_subdirectory(bindings)

configure_file(
cmake/vtTVConfig.cmake.in
Expand All @@ -70,34 +74,3 @@ install(
DESTINATION cmake
COMPONENT lib
)

if (vt_tv_python_bindings_enabled)
# Build the core parts of nanobind once
nanobind_build_library(nanobind SHARED)

# Compile an extension library
add_library(my_ext MODULE ${CMAKE_CURRENT_SOURCE_DIR}/circle.cc)

# .. and link it against the nanobind parts
message(STATUS "vtk libraries: ${VTK_LIBRARIES}")
target_link_libraries(my_ext PUBLIC ${VTK_LIBRARIES})
target_link_libraries(my_ext PRIVATE nanobind)

# .. enable size optimizations
nanobind_opt_size(my_ext)

# .. enable link time optimization
nanobind_lto(my_ext)

# .. disable the stack protector
nanobind_disable_stack_protector(my_ext)

# .. set the Python extension suffix
nanobind_extension(my_ext)

# .. set important compilation flags
nanobind_compile_options(my_ext)

# .. set important linker flags
nanobind_link_options(my_ext)
endif()
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,43 @@ using Paraview. Additionally, the task visualizer can produce PNGs
directly using a VTK workflow to render a visualization of ranks and
tasks over phases.

![Example Output PNG](./docs/example-output-image.png)
![Example Output PNG](./docs/example-output-image.png)

## Building the Python bindings

### Requirements

In order to build the python bindings, make sure you have a Python <ins>`3.8` or `3.9`</ins> environment, with the `nanobind` package installed. You can install `nanobind` with `pip`:

```bash
pip install nanobind
```

You must have a C++ compiler that supports C++17, and `cmake` >= 3.17.

Finally, you must have a (<ins>C++</ins>) [VTK](https://vtk.org/) build available on your system. We recommend building from source, and the currently tested version is `9.3.0`. You can find instructions for building VTK [here](https://gitlab.kitware.com/vtk/vtk/-/blob/master/Documentation/docs/build_instructions/build.md).

### Building

To build the python bindings, you must specify in the `VTTV_VTK_DIR` environment variable the path to the VTK build directory:

```bash
export VTTV_VTK_DIR=/path/to/vtk/build
```


Then, to install python-environment-wide the binded `vt-tv` python module, run:

```bash
pip install <path/to/vt-tv/source>
```
**Optional**

To specify the number of parallel jobs to use during the build, you can set the `VTTV_J` environment variable:

```bash
export VTTV_J=8
```

> [!NOTE]
> Behind the scenes, the usual `cmake` and `make` commands are run. Depending on your system, this can cause the install process to be lengthy as it will be compiling the entire `vt-tv` library.
6 changes: 6 additions & 0 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,10 @@ foreach(APP_FULL ${PROJECT_APPS})
PUBLIC
${VT_TV_LIBRARY_NS}
)

vtk_module_autoinit(
TARGETS ${APP}
MODULES ${VTK_LIBRARIES}
)

endforeach()
3 changes: 3 additions & 0 deletions bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if(VT_TV_PYTHON_BINDINGS_ENABLED)
add_subdirectory(python)
endif()
21 changes: 21 additions & 0 deletions bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

# Source files for the Python bindings
file(
GLOB
PYTHON_BINDING_SRCS
"${CMAKE_CURRENT_SOURCE_DIR}/*.cc"
)

# Build the core parts of nanobind once
nanobind_build_library(nanobind SHARED)

# Create the Python bindings for the module
nanobind_add_module(vttv ${PYTHON_BINDING_SRCS} tv.cc)

# .. Link it to necessary libraries
target_link_libraries(vttv PUBLIC ${VT_TV_LIBRARY_NS} ${JSON_LIBRARY} ${FMT_LIBRARY})

vtk_module_autoinit(
TARGETS vttv
MODULES ${VTK_LIBRARIES}
)
140 changes: 140 additions & 0 deletions bindings/python/tv.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include "tv.h"

namespace vt::tv::bindings::python {

void tvFromJson(const std::vector<std::string>& input_json_per_rank_list, const std::string& input_yaml_params_str, uint64_t num_ranks) {
std::string startup_logo = std::string(" __ __\n")
cwschilly marked this conversation as resolved.
Show resolved Hide resolved
+ std::string(" _ __/ /_ / /__ __\n")
+ std::string("| | / / __/ _____ / __/ | / /\n")
+ std::string("| |/ / / /____/ / /_ | |/ /\n")
+ std::string("|___/\\__/ \\__/ |___/\n");
fmt::print("==============================\n");
fmt::print(startup_logo);
fmt::print("==============================\n");

// parse the input yaml parameters
try {
// Load the configuration from serialized YAML
YAML::Node viz_config = YAML::Load(input_yaml_params_str);


std::array<std::string, 3> qoi_request = {
viz_config["rank_qoi"].as<std::string>(),
"",
viz_config["object_qoi"].as<std::string>()
};

bool save_meshes = viz_config["save_meshes"].as<bool>();
bool save_pngs = true; // lbaf always saves pngs
bool continuous_object_qoi = viz_config["force_continuous_object_qoi"].as<bool>();

std::array<uint64_t, 3> grid_size = {
viz_config["x_ranks"].as<uint64_t>(),
viz_config["y_ranks"].as<uint64_t>(),
viz_config["z_ranks"].as<uint64_t>()
};

double object_jitter = viz_config["object_jitter"].as<double>();

std::string output_dir = viz_config["output_visualization_dir"].as<std::string>();
std::filesystem::path output_path(output_dir);

// Throw an error if the output directory does not exist or is not absolute
if (!std::filesystem::exists(output_path)) {
throw std::runtime_error("Visualization output directory does not exist.");
}
if (!output_path.is_absolute()) {
throw std::runtime_error("Visualization output directory must be absolute.");
}

// append / to avoid problems with file stems
if (!output_dir.empty() && output_dir.back() != '/') {
output_dir += '/';
}

std::string output_file_stem = viz_config["output_visualization_file_stem"].as<std::string>();

uint64_t win_size = 2000;
if (viz_config["window_size"]) {
win_size = viz_config["window_size"].as<uint64_t>();
}

// Use automatic font size if not defined by user
// 0.025 is the factor of the window size determined to be ideal for the font size
uint64_t font_size = 0.025 * win_size;
if (viz_config["font_size"]) {
font_size = viz_config["font_size"].as<uint64_t>();
}

// print all saved configuration parameters
fmt::print("Input Configuration Parameters:\n");
fmt::print(" x_ranks: {}\n", grid_size[0]);
fmt::print(" y_ranks: {}\n", grid_size[1]);
fmt::print(" z_ranks: {}\n", grid_size[2]);
fmt::print(" object_jitter: {}\n", object_jitter);
fmt::print(" rank_qoi: {}\n", qoi_request[0]);
fmt::print(" object_qoi: {}\n", qoi_request[2]);
fmt::print(" save_meshes: {}\n", save_meshes);
fmt::print(" save_pngs: {}\n", save_pngs);
fmt::print(" force_continuous_object_qoi: {}\n", continuous_object_qoi);
fmt::print(" output_visualization_dir: {}\n", output_dir);
fmt::print(" output_visualization_file_stem: {}\n", output_file_stem);
fmt::print(" window_size: {}\n", win_size);
fmt::print(" font_size: {}\n", font_size);

using json = nlohmann::json;

assert(input_json_per_rank_list.size() == num_ranks && "Must have the same number of json files as ranks");

// Initialize the info object, that will hold data for all ranks for all phases
std::unique_ptr<Info> info = std::make_unique<Info>();

#ifdef VT_TV_N_THREADS
const int threads = VT_TV_N_THREADS;
#else
const int threads = 2;
#endif
#ifdef VT_TV_OPENMP_ENABLED
#if VT_TV_OPENMP_ENABLED
omp_set_num_threads(threads);
// print number of threads
fmt::print("vt-tv: Using {} threads\n", threads);
# pragma omp parallel for
#endif
#endif
for (int64_t rank_id = 0; rank_id < num_ranks; rank_id++) {
fmt::print("Reading file for rank {}\n", rank_id);
std::string rank_json_str = input_json_per_rank_list[rank_id];
utility::JSONReader reader{static_cast<NodeType>(rank_id)};
reader.readString(rank_json_str);
auto tmpInfo = reader.parse();
#ifdef VT_TV_OPENMP_ENABLED
#if VT_TV_OPENMP_ENABLED
#pragma omp critical
#endif
#endif
{
info->addInfo(tmpInfo->getObjectInfo(), tmpInfo->getRank(rank_id));
}
}
// Instantiate render
Render render(
qoi_request, continuous_object_qoi, *info, grid_size, object_jitter,
output_dir, output_file_stem, 1.0, save_meshes, save_pngs, std::numeric_limits<PhaseType>::max()
);
render.generate(font_size, win_size);
} catch (std::exception const& e) {
std::cout << "vt-tv: Error reading the configuration file: " << e.what() << std::endl;
}

fmt::print("vt-tv: Done.\n");
}

namespace nb = nanobind;
using namespace nb::literals;

NB_MODULE(vttv, m) {
m.def("tvFromJson", &tvFromJson);
}

} /* end namespace vt::tv::bindings::python */
Loading
Loading