Skip to content

Commit

Permalink
Initial TBB import, pending MPI validation
Browse files Browse the repository at this point in the history
  • Loading branch information
tom91136 committed Aug 1, 2024
1 parent d8ff8dc commit 62bdfd9
Show file tree
Hide file tree
Showing 24 changed files with 3,755 additions and 9 deletions.
16 changes: 9 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ include(FetchContent)
######

if (NOT MODEL)

# set(MODEL std-indices)
# set(NVHPC_OFFLOAD cc60)
# set(CXX_EXTRA_FLAGS
Expand Down Expand Up @@ -184,19 +185,19 @@ if ((DEFINED CXX_EXTRA_FLAGS) AND (NOT DEFINED CXX_EXTRA_LINK_FLAGS))
set(CXX_EXTRA_LINK_FLAGS ${CXX_EXTRA_FLAGS})
endif ()

option(USE_TBB "Enable oneTBB library for *supported* models. Enabling this on models that
option(USE_ONETBB "Enable oneTBB library for *supported* models. Enabling this on models that
don't explicitly link against TBB is a no-op, see description of your selected
model on how this is used." OFF)

option(FETCH_TBB "Fetch (download) the oneTBB library for *supported* models. This uses CMake's
FetchContent feature. Specify version by setting FETCH_TBB_VERSION" OFF)
set(FETCH_TBB_VERSION "v2021.10.0" CACHE STRING "Specify version of oneTBB to use if FETCH_TBB is ON")
option(FETCH_ONETBB "Fetch (download) the oneTBB library for *supported* models. This uses CMake's
FetchContent feature. Specify version by setting FETCH_ONETBB_VERSION" OFF)
set(FETCH_ONETBB_VERSION "v2021.10.0" CACHE STRING "Specify version of oneTBB to use if FETCH_ONETBB is ON")

if (FETCH_TBB)
if (FETCH_ONETBB)
FetchContent_Declare(
TBB
GIT_REPOSITORY https://github.com/oneapi-src/oneTBB.git
GIT_TAG "${FETCH_TBB_VERSION}"
GIT_TAG "${FETCH_ONETBB_VERSION}"
)
# Don't fail builds on waring (TBB has -Wall while not being free of warnings from unused symbols...)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
Expand Down Expand Up @@ -232,7 +233,7 @@ if (FETCH_ONEDPL)
FetchContent_GetProperties(oneDPL)
if (NOT oneDPL_POPULATED)
FetchContent_Populate(oneDPL)
if (USE_TBB)
if (USE_ONETBB)
macro(find_package NAME)
if ("${NAME}" STREQUAL "TBB")
message(STATUS "Discarding oneDPL's call to find_package(${NAME} ${ARGN})")
Expand Down Expand Up @@ -305,6 +306,7 @@ register_model(serial USE_SERIAL ${MODEL_SRC})
register_model(cuda USE_CUDA ${MODEL_SRC})
register_model(hip USE_HIP ${MODEL_SRC})
register_model(std-indices USE_STD ${MODEL_SRC})
register_model(tbb USE_TBB ${MODEL_SRC})
register_model(kokkos USE_KOKKOS ${MODEL_SRC})
register_model(acc ACC ${MODEL_SRC})
register_model(sycl-acc USE_SYCL_ACC ${MODEL_SRC})
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ particular order:
- Kokkos >= 4
- SYCL and SYCL 2020
- OpenACC (special thanks to @pranav-sivaraman's contribution)
- TBB

Planned:

- RAJA
- TBB
- Thrust (via CUDA or HIP)

## Building
Expand Down
127 changes: 127 additions & 0 deletions src/tbb/PdV.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
Crown Copyright 2012 AWE.
This file is part of CloverLeaf.
CloverLeaf is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
CloverLeaf is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
CloverLeaf. If not, see http://www.gnu.org/licenses/.
*/

#include "PdV.h"
#include "comms.h"
#include "context.h"
#include "ideal_gas.h"
#include "report.h"
#include "revert.h"
#include "timer.h"
#include "update_halo.h"
#include <cmath>

// @brief Fortran PdV kernel.
// @author Wayne Gaudin
// @details Calculates the change in energy and density in a cell using the
// change on cell volume due to the velocity gradients in a cell. The time
// level of the velocity data depends on whether it is invoked as the
// predictor or corrector.
void PdV_kernel(bool predict, int x_min, int x_max, int y_min, int y_max, double dt, clover::Buffer2D<double> &xarea,
clover::Buffer2D<double> &yarea, clover::Buffer2D<double> &volume, clover::Buffer2D<double> &density0,
clover::Buffer2D<double> &density1, clover::Buffer2D<double> &energy0, clover::Buffer2D<double> &energy1,
clover::Buffer2D<double> &pressure, clover::Buffer2D<double> &viscosity, clover::Buffer2D<double> &xvel0,
clover::Buffer2D<double> &xvel1, clover::Buffer2D<double> &yvel0, clover::Buffer2D<double> &yvel1,
clover::Buffer2D<double> &volume_change) {

// DO k=y_min,y_max
// DO j=x_min,x_max
clover::Range2d policy(x_min + 1, y_min + 1, x_max + 2, y_max + 2);

if (predict) {

clover::par_ranged2(policy, [&](const int i, const int j) {
double left_flux = (xarea(i, j) * (xvel0(i, j) + xvel0(i + 0, j + 1) + xvel0(i, j) + xvel0(i + 0, j + 1))) * 0.25 * dt * 0.5;
double right_flux =
(xarea(i + 1, j + 0) * (xvel0(i + 1, j + 0) + xvel0(i + 1, j + 1) + xvel0(i + 1, j + 0) + xvel0(i + 1, j + 1))) * 0.25 * dt * 0.5;
double bottom_flux = (yarea(i, j) * (yvel0(i, j) + yvel0(i + 1, j + 0) + yvel0(i, j) + yvel0(i + 1, j + 0))) * 0.25 * dt * 0.5;
double top_flux =
(yarea(i + 0, j + 1) * (yvel0(i + 0, j + 1) + yvel0(i + 1, j + 1) + yvel0(i + 0, j + 1) + yvel0(i + 1, j + 1))) * 0.25 * dt * 0.5;
double total_flux = right_flux - left_flux + top_flux - bottom_flux;
double volume_change_s = volume(i, j) / (volume(i, j) + total_flux);
double recip_volume = 1.0 / volume(i, j);
double energy_change = (pressure(i, j) / density0(i, j) + viscosity(i, j) / density0(i, j)) * total_flux * recip_volume;
energy1(i, j) = energy0(i, j) - energy_change;
density1(i, j) = density0(i, j) * volume_change_s;
});

} else {

clover::par_ranged2(policy, [&](const int i, const int j) {
double left_flux = (xarea(i, j) * (xvel0(i, j) + xvel0(i + 0, j + 1) + xvel1(i, j) + xvel1(i + 0, j + 1))) * 0.25 * dt;
double right_flux =
(xarea(i + 1, j + 0) * (xvel0(i + 1, j + 0) + xvel0(i + 1, j + 1) + xvel1(i + 1, j + 0) + xvel1(i + 1, j + 1))) * 0.25 * dt;
double bottom_flux = (yarea(i, j) * (yvel0(i, j) + yvel0(i + 1, j + 0) + yvel1(i, j) + yvel1(i + 1, j + 0))) * 0.25 * dt;
double top_flux =
(yarea(i + 0, j + 1) * (yvel0(i + 0, j + 1) + yvel0(i + 1, j + 1) + yvel1(i + 0, j + 1) + yvel1(i + 1, j + 1))) * 0.25 * dt;
double total_flux = right_flux - left_flux + top_flux - bottom_flux;
double volume_change_s = volume(i, j) / (volume(i, j) + total_flux);
double recip_volume = 1.0 / volume(i, j);
double energy_change = (pressure(i, j) / density0(i, j) + viscosity(i, j) / density0(i, j)) * total_flux * recip_volume;
energy1(i, j) = energy0(i, j) - energy_change;
density1(i, j) = density0(i, j) * volume_change_s;
});
}
}

// @brief Driver for the PdV update.
// @author Wayne Gaudin
// @details Invokes the user specified kernel for the PdV update.
void PdV(global_variables &globals, bool predict) {

double kernel_time = 0;
if (globals.profiler_on) kernel_time = timer();

globals.error_condition = 0;

for (int tile = 0; tile < globals.config.tiles_per_chunk; ++tile) {
tile_type &t = globals.chunk.tiles[tile];
PdV_kernel(predict, t.info.t_xmin, t.info.t_xmax, t.info.t_ymin, t.info.t_ymax, globals.dt, t.field.xarea, t.field.yarea,
t.field.volume, t.field.density0, t.field.density1, t.field.energy0, t.field.energy1, t.field.pressure, t.field.viscosity,
t.field.xvel0, t.field.xvel1, t.field.yvel0, t.field.yvel1, t.field.work_array1);
}

clover_check_error(globals.error_condition);
if (globals.profiler_on) globals.profiler.PdV += timer() - kernel_time;

if (globals.error_condition == 1) {
report_error((char *)"PdV", (char *)"error in PdV");
}

if (predict) {
if (globals.profiler_on) kernel_time = timer();
for (int tile = 0; tile < globals.config.tiles_per_chunk; ++tile) {
ideal_gas(globals, tile, true);
}

if (globals.profiler_on) globals.profiler.ideal_gas += timer() - kernel_time;

int fields[NUM_FIELDS];
for (int &field : fields)
field = 0;
fields[field_pressure] = 1;
update_halo(globals, fields, 1);
}

if (predict) {
if (globals.profiler_on) kernel_time = timer();
revert(globals);
if (globals.profiler_on) globals.profiler.revert += timer() - kernel_time;
}
}
72 changes: 72 additions & 0 deletions src/tbb/accelerate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Crown Copyright 2012 AWE.
This file is part of CloverLeaf.
CloverLeaf is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
CloverLeaf is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
CloverLeaf. If not, see http://www.gnu.org/licenses/.
*/

#include "accelerate.h"
#include "context.h"
#include "timer.h"

// @brief Fortran acceleration kernel
// @author Wayne Gaudin
// @details The pressure and viscosity gradients are used to update the
// velocity field.
void accelerate_kernel(int x_min, int x_max, int y_min, int y_max, double dt, clover::Buffer2D<double> &xarea,
clover::Buffer2D<double> &yarea, clover::Buffer2D<double> &volume, clover::Buffer2D<double> &density0,
clover::Buffer2D<double> &pressure, clover::Buffer2D<double> &viscosity, clover::Buffer2D<double> &xvel0,
clover::Buffer2D<double> &yvel0, clover::Buffer2D<double> &xvel1, clover::Buffer2D<double> &yvel1) {

double halfdt = 0.5 * dt;

// DO k=y_min,y_max+1
// DO j=x_min,x_max+1
// Kokkos::MDRangePolicy <Kokkos::Rank<2>> policy({x_min + 1, y_min + 1},
// {x_max + 1 + 2, y_max + 1 + 2});

clover::par_ranged2(Range2d{x_min + 1, y_min + 1, x_max + 1 + 2, y_max + 1 + 2}, [&](const int i, const int j) {
double stepbymass_s = halfdt / ((density0(i - 1, j - 1) * volume(i - 1, j - 1) + density0(i - 1, j + 0) * volume(i - 1, j + 0) +
density0(i, j) * volume(i, j) + density0(i + 0, j - 1) * volume(i + 0, j - 1)) *
0.25);

xvel1(i, j) = xvel0(i, j) - stepbymass_s * (xarea(i, j) * (pressure(i, j) - pressure(i - 1, j + 0)) +
xarea(i + 0, j - 1) * (pressure(i + 0, j - 1) - pressure(i - 1, j - 1)));
yvel1(i, j) = yvel0(i, j) - stepbymass_s * (yarea(i, j) * (pressure(i, j) - pressure(i + 0, j - 1)) +
yarea(i - 1, j + 0) * (pressure(i - 1, j + 0) - pressure(i - 1, j - 1)));
xvel1(i, j) = xvel1(i, j) - stepbymass_s * (xarea(i, j) * (viscosity(i, j) - viscosity(i - 1, j + 0)) +
xarea(i + 0, j - 1) * (viscosity(i + 0, j - 1) - viscosity(i - 1, j - 1)));
yvel1(i, j) = yvel1(i, j) - stepbymass_s * (yarea(i, j) * (viscosity(i, j) - viscosity(i + 0, j - 1)) +
yarea(i - 1, j + 0) * (viscosity(i - 1, j + 0) - viscosity(i - 1, j - 1)));
});
}

// @brief Driver for the acceleration kernels
// @author Wayne Gaudin
// @details Calls user requested kernel
void accelerate(global_variables &globals) {

double kernel_time = 0;
if (globals.profiler_on) kernel_time = timer();

for (int tile = 0; tile < globals.config.tiles_per_chunk; ++tile) {
tile_type &t = globals.chunk.tiles[tile];

accelerate_kernel(t.info.t_xmin, t.info.t_xmax, t.info.t_ymin, t.info.t_ymax, globals.dt, t.field.xarea, t.field.yarea, t.field.volume,
t.field.density0, t.field.pressure, t.field.viscosity, t.field.xvel0, t.field.yvel0, t.field.xvel1, t.field.yvel1);
}

if (globals.profiler_on) globals.profiler.acceleration += timer() - kernel_time;
}
Loading

0 comments on commit 62bdfd9

Please sign in to comment.