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

Implement expand half to full (neighbor list) #809

Merged
merged 2 commits into from
Jan 4, 2023
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
67 changes: 67 additions & 0 deletions src/details/ArborX_DetailsExpandHalfToFull.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/****************************************************************************
* Copyright (c) 2017-2023 by the ArborX authors *
* All rights reserved. *
* *
* This file is part of the ArborX library. ArborX is *
* distributed under a BSD 3-clause license. For the licensing terms see *
* the LICENSE file in the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#ifndef ARBORX_DETAILS_EXPAND_HALF_TO_FULL_HPP
#define ARBORX_DETAILS_EXPAND_HALF_TO_FULL_HPP

#include <ArborX_DetailsKokkosExtViewHelpers.hpp>
#include <ArborX_DetailsUtils.hpp>

#include <Kokkos_Core.hpp>

namespace ArborX::Details
{

template <class ExecutionSpace, class Offsets, class Indices>
void expandHalfToFull(ExecutionSpace const &space, Offsets &offsets,
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a note to myself: may want to explore a version of the function where we construct an array of pairs (i, j) and (j, i), sort it, and then construct new indices and offsets.

Indices &indices)
{
Kokkos::Profiling::pushRegion("ArborX::Experimental::HalfToFull");
typename Offsets::const_type const offsets_orig = offsets;
typename Indices::const_type const indices_orig = indices;

auto const n = offsets.extent(0) - 1;
offsets = KokkosExt::cloneWithoutInitializingNorCopying(space, offsets_orig);
dalg24 marked this conversation as resolved.
Show resolved Hide resolved
Kokkos::deep_copy(space, offsets, 0);
Kokkos::parallel_for(
"ArborX::Experimental::HalfToFull::count",
Kokkos::RangePolicy<ExecutionSpace>(space, 0, n), KOKKOS_LAMBDA(int i) {
for (int j = offsets_orig(i); j < offsets_orig(i + 1); ++j)
{
int const k = indices_orig(j);
Kokkos::atomic_increment(&offsets(i));
Kokkos::atomic_increment(&offsets(k));
}
});
exclusivePrefixSum(space, offsets);

auto const m = KokkosExt::lastElement(space, offsets);
dalg24 marked this conversation as resolved.
Show resolved Hide resolved
KokkosExt::reallocWithoutInitializing(space, indices, m);

Offsets counts(
Kokkos::view_alloc(space, "ArborX::Experimental::HalfToFull::count"), n);
Kokkos::parallel_for(
"ArborX::Experimental::HalfToFull::rewrite",
Kokkos::RangePolicy<ExecutionSpace>(space, 0, n), KOKKOS_LAMBDA(int i) {
auto const offsets_i = offsets(i);
for (int j = offsets_orig(i); j < offsets_orig(i + 1); ++j)
{
int const k = indices_orig(j);
indices(offsets_i + Kokkos::atomic_fetch_inc(&counts(i))) = k;
indices(offsets(k) + Kokkos::atomic_fetch_inc(&counts(k))) = i;
}
});
Kokkos::Profiling::popRegion();
}

} // namespace ArborX::Details

#endif
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ add_test(NAME ArborX_Test_DetailsClusteringHelpers COMMAND ./ArborX_Test_Details

add_executable(ArborX_Test_SpecializedTraversals.exe
tstDetailsHalfTraversal.cpp
tstDetailsExpandHalfToFull.cpp
utf_main.cpp
)
target_link_libraries(ArborX_Test_SpecializedTraversals.exe PRIVATE ArborX Boost::unit_test_framework)
Expand Down
1 change: 1 addition & 0 deletions test/boost_ext/CompressedStorageComparison.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define ARBORX_BOOST_TEST_COMPRESSED_STORAGE_COMPARISON_HPP

#include <boost/test/tools/detail/print_helper.hpp>
#include <boost/test/utils/is_forward_iterable.hpp>

#include <iosfwd>
#include <set>
Expand Down
78 changes: 78 additions & 0 deletions test/tstDetailsExpandHalfToFull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/****************************************************************************
* Copyright (c) 2017-2023 by the ArborX authors *
* All rights reserved. *
* *
* This file is part of the ArborX library. ArborX is *
* distributed under a BSD 3-clause license. For the licensing terms see *
* the LICENSE file in the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

// clang-format off
#include "boost_ext/CompressedStorageComparison.hpp"
// clang-format on

#include "ArborXTest_StdVectorToKokkosView.hpp"
#include "ArborX_EnableDeviceTypes.hpp" // ARBORX_DEVICE_TYPES
#include "ArborX_EnableViewComparison.hpp"
#include <ArborX_DetailsExpandHalfToFull.hpp>

#include "BoostTest_CUDA_clang_workarounds.hpp"
#include <boost/test/unit_test.hpp>

namespace Test
{
using ArborXTest::toView;

template <class ExecutionSpace>
auto expand(ExecutionSpace space, std::vector<int> const &offsets_host,
std::vector<int> const &indices_host)
{
auto offsets = toView<ExecutionSpace>(offsets_host, "Test::offsets");
auto indices = toView<ExecutionSpace>(indices_host, "Test::indices");
ArborX::Details::expandHalfToFull(space, offsets, indices);

return make_compressed_storage(
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, offsets),
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, indices));
}

#define ARBORX_TEST_EXPAND_HALF_TO_FULL(exec_space, offsets_in, indices_in, \
offsets_out, indices_out) \
BOOST_TEST(Test::expand(exec_space, offsets_in, indices_in) == \
make_compressed_storage(offsets_out, indices_out), \
boost::test_tools::per_element())
Comment on lines +41 to +45
Copy link
Contributor

Choose a reason for hiding this comment

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

I would use _half and _full instead of _in and _out for clarity, and maybe add _ref to the full ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not changing


} // namespace Test

BOOST_AUTO_TEST_CASE_TEMPLATE(expand_half_to_full, DeviceType,
ARBORX_DEVICE_TYPES)
{
using ExecutionSpace = typename DeviceType::execution_space;
ExecutionSpace exec_space;

ARBORX_TEST_EXPAND_HALF_TO_FULL(exec_space, (std::vector<int>{0}),
(std::vector<int>{}), (std::vector<int>{0}),
(std::vector<int>{}));

// (0,0) -> (0,0)(0,0)
ARBORX_TEST_EXPAND_HALF_TO_FULL(
exec_space, (std::vector<int>{0, 1}), (std::vector<int>{0}),
(std::vector<int>{0, 2}), (std::vector<int>{0, 0}));
Comment on lines +60 to +62
Copy link
Contributor

Choose a reason for hiding this comment

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

I must be missing something here and in the rest of the tests.

It seems that you are testing the expand function on the input that would be invalid outputs for the half traversal. In this particular case, you have a single element (0, 0) in the half-list, and it produces two (0, 0) in the output. This does not seem right.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added comments explaining what each assertion is checking in pair format


// (0,0)(0,0) -> (0,0)(0,0)(0,0)(0,0)
ARBORX_TEST_EXPAND_HALF_TO_FULL(
exec_space, (std::vector<int>{0, 2}), (std::vector<int>{0, 0}),
(std::vector<int>{0, 4}), (std::vector<int>{0, 0, 0, 0}));

// (0,0)(0,1) -> (0,0)(0,1)(0,0)(1,0)
ARBORX_TEST_EXPAND_HALF_TO_FULL(
exec_space, (std::vector<int>{0, 2, 2}), (std::vector<int>{0, 1}),
(std::vector<int>{0, 3, 4}), (std::vector<int>{0, 1, 0, 0}));

// (1,0) -> (0,1)(1,0)
ARBORX_TEST_EXPAND_HALF_TO_FULL(
exec_space, (std::vector<int>{0, 0, 1, 1, 1}), (std::vector<int>{0}),
(std::vector<int>{0, 1, 2, 2, 2}), (std::vector<int>{1, 0}));
}