Skip to content

Commit

Permalink
Update the bufSlicingTest
Browse files Browse the repository at this point in the history
Update the comments and simplify the code.
Invert the logic to avoid spurious unreachable code warnings.
Add a second test for the memset functionality on a slice.

Signed-off-by: Andrea Bocci <andrea.bocci@cern.ch>
  • Loading branch information
fwyzard authored and bernhardmgruber committed Jul 24, 2023
1 parent 6abab49 commit eab49ee
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 48 deletions.
2 changes: 1 addition & 1 deletion test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ add_subdirectory("math/")
add_subdirectory("mem/buf/")
add_subdirectory("mem/copy/")
add_subdirectory("mem/fence/")
add_subdirectory("mem/view/")
add_subdirectory("mem/p2p/")
add_subdirectory("mem/view/")
add_subdirectory("meta/")
add_subdirectory("queue/")
add_subdirectory("rand/")
Expand Down
151 changes: 104 additions & 47 deletions test/unit/mem/copy/src/BufSlicing.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2022 Axel Huebl, Benjamin Worpitz, Jakob Krude, Bernhard Manfred Gruber, Jan Stephan
/* Copyright 2023 Axel Huebl, Benjamin Worpitz, Jakob Krude, Bernhard Manfred Gruber, Jan Stephan, Andrea Bocci
* SPDX-License-Identifier: MPL-2.0
*/

Expand Down Expand Up @@ -37,7 +37,6 @@ struct TestContainer
DevHost const devHost;
DevQueue devQueue;


// Constructor
TestContainer()
: devAcc(alpaka::getDevByIdx<PltfAcc>(0u))
Expand All @@ -46,42 +45,37 @@ struct TestContainer
{
}


auto createHostBuffer(Vec extents, bool indexed) -> BufHost
{
BufHost bufHost(alpaka::allocBuf<TData, TIdx>(devHost, extents));
if(indexed)
{
TData* const ptr = alpaka::getPtrNative(bufHost);
for(TIdx i(0); i < extents.prod(); ++i)
TData* const ptr = bufHost.data();
for(TIdx i = 0; i < extents.prod(); ++i)
{
ptr[i] = static_cast<TData>(i);
}
}
return bufHost;
}


auto createDeviceBuffer(Vec extents) -> BufDevice
{
BufDevice bufDevice(alpaka::allocBuf<TData, TIdx>(devAcc, extents));
return bufDevice;
}


auto copyToAcc(BufHost bufHost, BufDevice bufAcc, Vec extents) -> void
{
alpaka::memcpy(devQueue, bufAcc, bufHost, extents);
}


auto copyToHost(BufDevice bufAcc, BufHost bufHost, Vec extents) -> void
{
alpaka::memcpy(devQueue, bufHost, bufAcc, extents);
}


auto sliceOnDevice(BufDevice bufferToBeSliced, Vec subViewExtents, Vec offsets) -> BufDevice
auto copySliceOnDevice(BufDevice bufferToBeSliced, Vec subViewExtents, Vec offsets) -> BufDevice
{
BufDevice slicedBuffer = createDeviceBuffer(subViewExtents);
// Create a subView with a possible offset.
Expand All @@ -91,12 +85,19 @@ struct TestContainer
return slicedBuffer;
}

auto zeroSliceOnDevice(BufDevice bufferToBeSliced, Vec subViewExtents, Vec offsets) -> void
{
// Create a subView with a possible offset.
SubView subView = SubView(bufferToBeSliced, subViewExtents, offsets);
// Fill the subView with zeros.
alpaka::memset(devQueue, subView, 0u);
}

auto compareBuffer(BufHost const& bufferA, BufHost const& bufferB, Vec const& extents) const
{
TData const* const ptrA = alpaka::getPtrNative(bufferA);
TData const* const ptrB = alpaka::getPtrNative(bufferB);
for(TIdx i(0); i < extents.prod(); ++i)
TData const* const ptrA = bufferA.data();
TData const* const ptrB = bufferB.data();
for(TIdx i = 0; i < extents.prod(); ++i)
{
INFO("Dim: " << TDim::value);
INFO("Idx: " << alpaka::core::demangled<TIdx>);
Expand All @@ -111,57 +112,113 @@ using DataTypes = std::tuple<int, float, double>;

using TestAccWithDataTypes = alpaka::meta::CartesianProduct<std::tuple, alpaka::test::TestAccs, DataTypes>;

TEMPLATE_LIST_TEST_CASE("memBufSlicingTest", "[memBuf]", TestAccWithDataTypes)
TEMPLATE_LIST_TEST_CASE("memBufSlicingMemcpyTest", "[memBuf]", TestAccWithDataTypes)
{
using Acc = std::tuple_element_t<0, TestType>;
using Data = std::tuple_element_t<1, TestType>;
using Dim = alpaka::Dim<Acc>;
// fourth-dimension is not supposed to be tested currently
if(Dim::value == 4)
using Idx = alpaka::Idx<Acc>;

// Test only buffer slices with up to three dimensions.
if constexpr(Dim::value < 4)
{
return;
TestContainer<Dim, Idx, Acc, Data> slicingTest;

auto const extents
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForExtentBuf>();
auto const extentsSubView
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForExtentSubView>();
auto const offsets
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForOffset>();

// This is the initial buffer.
auto const indexedBuffer = slicingTest.createHostBuffer(extents, true);

// This buffer will hold the copy of the initial buffer on the device.
auto deviceBuffer = slicingTest.createDeviceBuffer(extents);

// This buffer will hold the sliced-buffer when it is copied back to the host.
auto resultBuffer = slicingTest.createHostBuffer(extentsSubView, false);

// Copy the initial buffer to the device.
slicingTest.copyToAcc(indexedBuffer, deviceBuffer, extents);

// Make a copy of a slice of the buffer on the device.
auto slicedBuffer = slicingTest.copySliceOnDevice(deviceBuffer, extentsSubView, offsets);

// Copy the slice back to the host.
slicingTest.copyToHost(slicedBuffer, resultBuffer, extentsSubView);

// Compute the expected content of the slice.
using Dim1 = alpaka::DimInt<1u>;
auto correctResults = slicingTest.createHostBuffer(extentsSubView, false);
Data* const ptr = correctResults.data();
for(Idx i = 0; i < extentsSubView.prod(); ++i)
{
auto mappedToND = alpaka::mapIdx<Dim::value, Dim1::value>(alpaka::Vec<Dim1, Idx>(i), extentsSubView);
auto addedOffset = mappedToND + offsets;
auto mappedTo1D = alpaka::mapIdx<Dim1::value>(
addedOffset,
extents)[0]; // take the only element in the vector
ptr[i] = static_cast<Data>(mappedTo1D);
}

// Compare the resultBuffer with the results computed manually.
slicingTest.compareBuffer(resultBuffer, correctResults, extentsSubView);
}
}

TEMPLATE_LIST_TEST_CASE("memBufSlicingMemsetTest", "[memBuf]", TestAccWithDataTypes)
{
using Acc = std::tuple_element_t<0, TestType>;
using Data = std::tuple_element_t<1, TestType>;
using Dim = alpaka::Dim<Acc>;
using Idx = alpaka::Idx<Acc>;
TestContainer<Dim, Idx, Acc, Data> slicingTest;

auto const extents
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForExtentBuf>();
// Test only buffer slices with up to three dimensions.
if constexpr(Dim::value < 4)
{
TestContainer<Dim, Idx, Acc, Data> slicingTest;

auto const extentsSubView
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForExtentSubView>();
auto const offsets
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForOffset>();
auto const extents
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForExtentBuf>();
auto const extentsSubView
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForExtentSubView>();
auto const offsets
= alpaka::createVecFromIndexedFn<Dim, alpaka::test::CreateVecWithIdx<Idx>::template ForOffset>();

// This is the initial buffer.
auto const indexedBuffer = slicingTest.createHostBuffer(extents, true);
// This buffer will hold the sliced-buffer when it was copied to the host.
auto resultBuffer = slicingTest.createHostBuffer(extentsSubView, false);
// This is the initial buffer.
auto const indexedBuffer = slicingTest.createHostBuffer(extents, true);

// Copy of the indexBuffer on the deviceSide.
auto deviceBuffer = slicingTest.createDeviceBuffer(extents);
// This buffer will hold the copy of the initial buffer on the device.
auto deviceBuffer = slicingTest.createDeviceBuffer(extents);

// Start: Main-Test
slicingTest.copyToAcc(indexedBuffer, deviceBuffer, extents);
// This buffer will hold a copy of the initial buffer, after a slice has been set to zeroes.
auto resultBuffer = slicingTest.createHostBuffer(extents, false);

auto slicedBuffer = slicingTest.sliceOnDevice(deviceBuffer, extentsSubView, offsets);
// Copy the initial buffer to the device.
slicingTest.copyToAcc(indexedBuffer, deviceBuffer, extents);

slicingTest.copyToHost(slicedBuffer, resultBuffer, extentsSubView);
// Fill a slice of the buffer with zeroes.
slicingTest.zeroSliceOnDevice(deviceBuffer, extentsSubView, offsets);

auto correctResults = slicingTest.createHostBuffer(extentsSubView, false);
Data* ptrNative = alpaka::getPtrNative(correctResults);
using Dim1 = alpaka::DimInt<1u>;
// Copy the buffer back to the host
slicingTest.copyToHost(deviceBuffer, resultBuffer, extents);

for(Idx i(0); i < extentsSubView.prod(); ++i)
{
auto mappedToND = alpaka::mapIdx<Dim::value, Dim1::value>(alpaka::Vec<Dim1, Idx>(i), extentsSubView);
auto addedOffset = mappedToND + offsets;
auto mappedTo1D = alpaka::mapIdx<Dim1::value>(addedOffset,
extents)[0]; // take the only element in the vector
ptrNative[i] = static_cast<Data>(mappedTo1D);
}
// Compute the expected content of the buffer, with a slice set to zeroes.
using Dim1 = alpaka::DimInt<1u>;
auto correctResults = slicingTest.createHostBuffer(extents, true);
Data* const ptr = correctResults.data();
for(Idx i = 0; i < extents.prod(); ++i)
{
auto mappedToND = alpaka::mapIdx<Dim::value, Dim1::value>(alpaka::Vec<Dim1, Idx>(i), extents);
if((mappedToND >= offsets && mappedToND < offsets + extentsSubView).all())
ptr[i] = static_cast<Data>(0u);
}

// resultBuffer will be compared with the manually computed results.
slicingTest.compareBuffer(resultBuffer, correctResults, extentsSubView);
// Compare the resultBuffer with the results computed manually.
slicingTest.compareBuffer(resultBuffer, correctResults, extentsSubView);
}
}

#if BOOST_COMP_MSVC || defined(BOOST_COMP_MSVC_EMULATED)
Expand Down

0 comments on commit eab49ee

Please sign in to comment.