Skip to content

Commit efb0563

Browse files
Add CloverLeaf benchmark
1 parent 690da67 commit efb0563

File tree

4 files changed

+559
-4
lines changed

4 files changed

+559
-4
lines changed

benchmarks/CMakeLists.txt

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
#
2-
# Copyright 2023 Benjamin Worpitz, Jan Stephan, Mehmet Yusufoglu
3-
# SPDX-License-Identifier: ISC
2+
#Copyright 2023 Benjamin Worpitz, Jan Stephan, Mehmet Yusufoglu
3+
#SPDX - License - Identifier : ISC
44
#
55

66
################################################################################
7-
# Required CMake version.
7+
#Required CMake version.
88
################################################################################
99

1010
cmake_minimum_required(VERSION 3.22)
1111

1212
project("alpakaBenchmarks" LANGUAGES CXX)
1313

1414
################################################################################
15-
# Add subdirectories.
15+
#Add subdirectories.
1616
################################################################################
1717

1818
add_subdirectory("babelstream/")
19+
add_subdirectory("cloverleaf/")

benchmarks/cloverleaf/CMakeLists.txt

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#
2+
# Copyright 2023 Erik Zenker, Benjamin Worpitz, Jan Stephan, Bernhard Manfred Gruber
3+
# SPDX-License-Identifier: ISC
4+
#
5+
6+
cmake_minimum_required(VERSION 3.22)
7+
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
8+
9+
project(cloverleaf LANGUAGES CXX)
10+
11+
if(NOT TARGET alpaka::alpaka)
12+
option(alpaka_USE_SOURCE_TREE "Use alpaka's source tree instead of an alpaka installation" OFF)
13+
if(alpaka_USE_SOURCE_TREE)
14+
# Don't build the benchmarks recursively
15+
set(alpaka_BUILD_BENCHMARKS OFF)
16+
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../.." "${CMAKE_BINARY_DIR}/alpaka")
17+
else()
18+
find_package(alpaka REQUIRED)
19+
endif()
20+
endif()
21+
22+
23+
set(_TARGET_NAME "cloverleaf")
24+
append_recursive_files_add_to_src_group("src/" "src/" "cpp" _FILES_SOURCE)
25+
26+
alpaka_add_executable(
27+
${_TARGET_NAME}
28+
${_FILES_SOURCE})
29+
30+
target_sources(cloverleaf
31+
PRIVATE
32+
src/cloverLeafKernels.hpp
33+
)
34+
35+
target_include_directories(
36+
${_TARGET_NAME}
37+
PRIVATE "src")
38+
39+
target_link_libraries(
40+
${_TARGET_NAME}
41+
PRIVATE common)
42+
43+
#Run as a ctest
44+
if(alpaka_CI)
45+
# Only run for release builds since this is a benchmark
46+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
47+
set_target_properties(${_TARGET_NAME} PROPERTIES FOLDER benchmarks/cloverleaf)
48+
add_test(NAME ${_TARGET_NAME} COMMAND ${_TARGET_NAME} --benchmark-samples 1 -r xml)
49+
endif()
50+
else()
51+
# For a normal benchmark test, number of samples should be equal to the default value.
52+
add_test(NAME ${_TARGET_NAME} COMMAND ${_TARGET_NAME})
53+
endif()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#pragma once
2+
3+
#include <alpaka/alpaka.hpp>
4+
5+
#include <experimental/mdspan>
6+
7+
using Data = float;
8+
using Dim3 = alpaka::DimInt<3>;
9+
using Idx = std::uint32_t;
10+
11+
const Idx nx = 512; // Number of cells in x direction
12+
const Idx ny = 512; // Number of cells in y direction
13+
const Idx nz = 512; // Number of cells in z direction
14+
15+
// Kernel to initialize the simulation variables
16+
struct InitializerKernel
17+
{
18+
template<typename TAcc, typename MdSpan>
19+
ALPAKA_FN_ACC auto operator()(
20+
TAcc const& acc,
21+
MdSpan density,
22+
MdSpan energy,
23+
MdSpan pressure,
24+
MdSpan velocityX,
25+
MdSpan velocityY,
26+
MdSpan velocityZ) const -> void
27+
{
28+
// Get thread index, the center of filter-matrix is positioned to the item on this index.
29+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
30+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
31+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
32+
33+
if(i < nx && j < ny && k < nz)
34+
{
35+
density(i, j, k) = 1.0f; // Initial density
36+
energy(i, j, k) = 1.0f; // Initial energy
37+
pressure(i, j, k) = 1.0f; // Initial pressure
38+
velocityX(i, j, k) = 0.0f; // Initial velocity in x direction
39+
velocityY(i, j, k) = 0.0f; // Initial velocity in y direction
40+
velocityZ(i, j, k) = 0.0f; // Initial velocity in z direction
41+
}
42+
}
43+
};
44+
45+
// Kernel to compute the equation of state (EOS) and additional calculations
46+
struct EOSKernel
47+
{
48+
template<typename TAcc, typename MdSpan>
49+
ALPAKA_FN_ACC auto operator()(
50+
TAcc const& acc,
51+
MdSpan density,
52+
MdSpan energy,
53+
MdSpan pressure,
54+
MdSpan velocityX,
55+
MdSpan velocityY,
56+
MdSpan velocityZ,
57+
float gamma) const -> void
58+
{
59+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
60+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
61+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
62+
63+
if(i < nx && j < ny && k < nz)
64+
{
65+
// Compute pressure using ideal gas law: P = (gamma - 1) * density * energy
66+
pressure(i, j, k) = (gamma - 1.0f) * density(i, j, k) * energy(i, j, k);
67+
68+
// Additional calculations to update velocities (this is a simplified example)
69+
velocityX(i, j, k) += pressure(i, j, k) * 0.1f;
70+
velocityY(i, j, k) += pressure(i, j, k) * 0.1f;
71+
velocityZ(i, j, k) += pressure(i, j, k) * 0.1f;
72+
}
73+
}
74+
};
75+
76+
// Kernel for Flux calculations
77+
struct FluxKernel
78+
{
79+
template<typename TAcc, typename MdSpan>
80+
ALPAKA_FN_ACC auto operator()(
81+
TAcc const& acc,
82+
MdSpan density,
83+
MdSpan energy,
84+
MdSpan pressure,
85+
MdSpan velocityX,
86+
MdSpan velocityY,
87+
MdSpan velocityZ,
88+
MdSpan fluxDensity,
89+
MdSpan fluxEnergy,
90+
MdSpan fluxVelocityX,
91+
MdSpan fluxVelocityY,
92+
MdSpan fluxVelocityZ) const -> void
93+
{
94+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
95+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
96+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
97+
98+
if(i < nx && j < ny && k < nz)
99+
{
100+
// Compute fluxes (this is a simplified example)
101+
fluxDensity(i, j, k) = density(i, j, k) * velocityX(i, j, k);
102+
fluxEnergy(i, j, k) = energy(i, j, k) * velocityX(i, j, k);
103+
fluxVelocityX(i, j, k) = velocityX(i, j, k) * velocityX(i, j, k) + pressure(i, j, k);
104+
fluxVelocityY(i, j, k) = velocityY(i, j, k) * velocityX(i, j, k);
105+
fluxVelocityZ(i, j, k) = velocityZ(i, j, k) * velocityX(i, j, k);
106+
}
107+
}
108+
};
109+
110+
// Kernel for the advection step
111+
struct AdvectionKernel
112+
{
113+
template<typename TAcc, typename MdSpan>
114+
ALPAKA_FN_ACC auto operator()(
115+
TAcc const& acc,
116+
MdSpan density,
117+
MdSpan velocityX,
118+
MdSpan velocityY,
119+
MdSpan velocityZ) const -> void
120+
{
121+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
122+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
123+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
124+
125+
if(i < nx && j < ny && k < nz)
126+
{
127+
// Simple advection calculation (this is a simplified example)
128+
density(i, j, k) += (velocityX(i, j, k) + velocityY(i, j, k) + velocityZ(i, j, k)) * 0.01f;
129+
}
130+
}
131+
};
132+
133+
struct LagrangianKernel
134+
{
135+
template<typename TAcc, typename MdSpan>
136+
ALPAKA_FN_ACC auto operator()(
137+
TAcc const& acc,
138+
MdSpan density,
139+
MdSpan energy,
140+
MdSpan velocityX,
141+
MdSpan velocityY,
142+
MdSpan velocityZ,
143+
MdSpan fluxDensity,
144+
MdSpan fluxEnergy,
145+
MdSpan fluxVelocityX,
146+
MdSpan fluxVelocityY,
147+
MdSpan fluxVelocityZ) const -> void
148+
{
149+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
150+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
151+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
152+
153+
if(i < nx && j < ny && k < nz)
154+
{
155+
// Update the cell-centered variables based on flux calculations
156+
density(i, j, k) -= fluxDensity(i, j, k) * 0.1f;
157+
energy(i, j, k) -= fluxEnergy(i, j, k) * 0.1f;
158+
velocityX(i, j, k) -= fluxVelocityX(i, j, k) * 0.1f;
159+
velocityY(i, j, k) -= fluxVelocityY(i, j, k) * 0.1f;
160+
velocityZ(i, j, k) -= fluxVelocityZ(i, j, k) * 0.1f;
161+
}
162+
}
163+
};
164+
165+
struct ViscosityKernel
166+
{
167+
template<typename TAcc, typename MdSpan>
168+
ALPAKA_FN_ACC auto operator()(
169+
TAcc const& acc,
170+
MdSpan density,
171+
MdSpan velocityX,
172+
MdSpan velocityY,
173+
MdSpan velocityZ,
174+
MdSpan pressure,
175+
MdSpan viscosity) const -> void
176+
{
177+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
178+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
179+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
180+
181+
if(i < nx && j < ny && k < nz)
182+
{
183+
// Calculate artificial viscosity (this is a simplified example)
184+
float gradVx = (velocityX(i + 1, j, k) - velocityX(i - 1, j, k)) * 0.5f;
185+
float gradVy = (velocityY(i, j + 1, k) - velocityY(i, j - 1, k)) * 0.5f;
186+
float gradVz = (velocityZ(i, j, k + 1) - velocityZ(i, j, k - 1)) * 0.5f;
187+
188+
viscosity(i, j, k) = density(i, j, k) * (gradVx * gradVx + gradVy * gradVy + gradVz * gradVz) * 0.01f;
189+
190+
// Apply viscosity to pressure
191+
pressure(i, j, k) += viscosity(i, j, k);
192+
}
193+
}
194+
};
195+
196+
struct MaxVelocityKernel
197+
{
198+
template<typename TAcc, typename MdSpan>
199+
ALPAKA_FN_ACC auto operator()(
200+
TAcc const& acc,
201+
MdSpan velocityX,
202+
MdSpan velocityY,
203+
MdSpan velocityZ,
204+
float* maxVelocity) const -> void
205+
{
206+
auto const i = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0];
207+
auto const j = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[1];
208+
auto const k = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[2];
209+
210+
if(i < nx && j < ny && k < nz)
211+
{
212+
float vx = velocityX(i, j, k);
213+
float vy = velocityY(i, j, k);
214+
float vz = velocityZ(i, j, k);
215+
float v = alpaka::math::sqrt(acc, (vx * vx + vy * vy + vz * vz));
216+
217+
// Atomic operation to find the maximum velocity
218+
alpaka::atomicMax(acc, maxVelocity, v);
219+
}
220+
}
221+
};
222+
223+
[[maybe_unused]] static float calculateTimeStep(float dx, float dy, float dz, float maxVelocity, float cMax)
224+
{
225+
// Compute the smallest grid spacing
226+
float minDx = std::min({dx, dy, dz});
227+
228+
// Calculate the time step based on the CFL condition
229+
float dt = cMax * minDx / maxVelocity;
230+
231+
return dt;
232+
}

0 commit comments

Comments
 (0)