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

Port generic alpaka phi functions to DataFormats/Math #47033

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions HeterogeneousCore/AlpakaMath/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<use name="alpaka"/>
<export>
<lib name="1"/>
</export>
35 changes: 35 additions & 0 deletions HeterogeneousCore/AlpakaMath/interface/deltaPhi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef HeterogeneousCore_AlpakaMath_deltaPhi_h
#define HeterogeneousCore_AlpakaMath_deltaPhi_h

#include <alpaka/alpaka.hpp>

namespace cms::alpakatools {

// reduce to [-pi,pi]
template <typename TAcc, std::floating_point T>
ALPAKA_FN_HOST_ACC inline T reduceRange(TAcc const& acc, T x) {
constexpr T o2pi = T{1.} / (T{2.} * std::numbers::pi_v<T>);
VourMa marked this conversation as resolved.
Show resolved Hide resolved
if (alpaka::math::abs(acc, x) <= std::numbers::pi_v<T>)
return x;
T n = alpaka::math::round(acc, x * o2pi);
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious: why not simply

Suggested change
T n = alpaka::math::round(acc, x * o2pi);
T n = alpaka::math::round(acc, x / (T{2} * std::numbers::pi_v<T>));

or

Suggested change
T n = alpaka::math::round(acc, x * o2pi);
T n = alpaka::math::round(acc, x * std::numbers::inv_pi_v<T> * T{0.5});

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As initially mentioned, this was meant to be an alpaka-adjusted copy of the reco::reduceRange function

constexpr T reduceRange(T x) {
constexpr T o2pi = 1. / (2. * M_PI);
if (std::abs(x) <= T(M_PI))
return x;
T n = std::round(x * o2pi);
return x - n * T(2. * M_PI);
}

hence I didn't apply any other simplifications, apart from the ones suggested in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok

return x - n * T{2.} * std::numbers::pi_v<T>;
}

template <typename TAcc, typename T>
ALPAKA_FN_HOST_ACC inline T phi(TAcc const& acc, T x, T y) {
return reduceRange(acc, std::numbers::pi_v<T> + alpaka::math::atan2(acc, -y, -x));
}

template <typename TAcc, typename T>
ALPAKA_FN_HOST_ACC inline T deltaPhi(TAcc const& acc, T x1, T y1, T x2, T y2) {
return reduceRange(acc, alpaka::math::atan2(acc, -y2, -x2) - alpaka::math::atan2(acc, -y1, -x1));
}

template <typename TAcc, typename T>
ALPAKA_FN_HOST_ACC inline T deltaPhi(TAcc const& acc, T phi1, T phi2) {
return reduceRange(acc, phi1 - phi2);
}

} // namespace cms::alpakatools

#endif
6 changes: 6 additions & 0 deletions HeterogeneousCore/AlpakaMath/test/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<bin name="alpakaTestDeltaPhi" file="alpaka/testDeltaPhi.dev.cc">
<use name="alpaka"/>
<use name="catch2"/>
<use name="HeterogeneousCore/AlpakaInterface"/>
<flags ALPAKA_BACKENDS="1"/>
</bin>
95 changes: 95 additions & 0 deletions HeterogeneousCore/AlpakaMath/test/alpaka/testDeltaPhi.dev.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <numbers>
#include <vector>

#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
#include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
#include "HeterogeneousCore/AlpakaInterface/interface/workdivision.h"
#include "HeterogeneousCore/AlpakaMath/interface/deltaPhi.h"

using namespace cms::alpakatools;
using namespace ALPAKA_ACCELERATOR_NAMESPACE;

struct phiFuncsUnitTestsKernel {
template <typename TAcc, typename T>
ALPAKA_FN_ACC void operator()(TAcc const& acc, T* out) const {
// Unit circle typical values
out[0] = phi<TAcc, T>(acc, 1.0, 0.0); // x = 1.0, y = 0.0 => phi = 0
out[1] = phi<TAcc, T>(acc, 0.0, 1.0); // x = 0.0, y = 1.0 => phi = pi/2
out[2] = phi<TAcc, T>(acc, -1.0, 0.0); // x = -1.0, y = 0.0 => phi = pi
out[3] = phi<TAcc, T>(acc, 0.0, -1.0); // x = 0.0, y = -1.0 => phi = -pi/2
out[4] = phi<TAcc, T>(acc, 0.7071, 0.7071); // x = sqrt(2)/2, y = sqrt(2)/2 => phi = pi/4
out[5] = phi<TAcc, T>(acc, -0.7071, -0.7071); // x = sqrt(2)/2, y = sqrt(2)/2 => phi = -3pi/4

// Making sure that delta phi is within [-pi, pi] range
// Phi from unit circle
out[6] = deltaPhi<TAcc, T>(acc, 1.0, 0.0, 0.0, -1.0); // 3pi/2 - 0 = -pi/2
out[7] = deltaPhi<TAcc, T>(acc, 0.0, 1.0, 0.0, -1.0); // 3pi/2 - pi/2 = pi
out[8] = deltaPhi<TAcc, T>(acc, 0.0, -1.0, 0.0, 1.0); // pi/2 - 3pi/2 = -pi
out[9] = deltaPhi<TAcc, T>(acc, 0.7071, -0.7071, -0.7071, -0.7071); // -3pi/4 - (-pi/4) = -pi/2

// Calculation directly from phi
out[10] = deltaPhi<TAcc, T>(acc, 3. * M_PI / 2., 0.); // 3pi/2 - 0 = -pi/2
out[11] = deltaPhi<TAcc, T>(acc, 3. * M_PI / 2., M_PI / 2.); // 3pi/2 - pi/2 = pi
out[12] = deltaPhi<TAcc, T>(acc, M_PI / 2., 3. * M_PI / 2.); // pi/2 - 3pi/2 = -pi
out[13] = deltaPhi<TAcc, T>(acc, -3. * M_PI / 4., -M_PI / 4.); // -3pi/4 - (-pi/4) = -pi/2
}
};

template <typename T>
void testPhiFuncs(uint32_t size, std::vector<double> const& res) {
// get the list of devices on the current platform
auto const& devices = cms::alpakatools::devices<Platform>();
if (devices.empty()) {
FAIL("No devices available for the " EDM_STRINGIZE(ALPAKA_ACCELERATOR_NAMESPACE) " backend, "
"the test will be skipped.");
}

for (auto const& device : devices) {
std::cout << "...on " << alpaka::getName(device) << "\n";
Queue queue(device);

auto c_h = make_host_buffer<T[]>(queue, size);
alpaka::memset(queue, c_h, 0.);
auto c_d = make_device_buffer<T[]>(queue, size);
alpaka::memset(queue, c_d, 0.);

alpaka::exec<Acc1D>(queue, WorkDiv1D{1u, 1u, 1u}, phiFuncsUnitTestsKernel(), c_d.data());
alpaka::memcpy(queue, c_h, c_d);
alpaka::wait(queue);

constexpr T eps = 1.e-5;
for (size_t i = 0; i < size; ++i) {
CHECK_THAT(c_h.data()[i], Catch::Matchers::WithinAbs(res[i], eps));
}
}
}

TEST_CASE("Standard checks alpaka phi functions for the relevant data types (float and double) and for all backends") {
std::vector<double> res = {0.0,
M_PI / 2.,
M_PI,
-M_PI / 2.,
M_PI / 4.,
-3. * M_PI / 4.,
-M_PI / 2.,
M_PI,
-M_PI,
-M_PI / 2.,
-M_PI / 2.,
M_PI,
-M_PI,
-M_PI / 2.}; // Expected results
uint32_t size = res.size(); // Number of tests

SECTION("Tests for double data type") {
std::cout << "Testing phi functions for double data type...\n";
testPhiFuncs<double>(size, res);
}

SECTION("Tests for float data type") {
std::cout << "Testing phi functions for float data type...\n";
testPhiFuncs<float>(size, res);
}
}