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

Add transfer function #828

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ if (UMPIRE_ENABLE_OPENMP_TARGET)
openmp)
endif()

blt_add_executable(
NAME transfer
SOURCES transfer.cpp
DEPENDS_ON ${example_depends}
)

blt_add_executable(
NAME aligned_allocator
SOURCES aligned_allocator.cpp
Expand Down
25 changes: 25 additions & 0 deletions examples/transfer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-23, Lawrence Livermore National Security, LLC and Umpire
// project contributors. See the COPYRIGHT file for details.
//
// SPDX-License-Identifier: (MIT)
//////////////////////////////////////////////////////////////////////////////
#include <iostream>

#include "umpire/ResourceManager.hpp"
#include "umpire/strategy/NamedAllocationStrategy.hpp"

int main(int, char**)
{
auto& rm = umpire::ResourceManager::getInstance();
auto alloc_one = rm.makeAllocator<umpire::strategy::NamedAllocationStrategy>("named_one", rm.getAllocator("HOST"));
auto alloc_two = rm.makeAllocator<umpire::strategy::NamedAllocationStrategy>("named_two", rm.getAllocator("HOST"));

void* test = alloc_one.allocate(100);

rm.transfer(test, alloc_two);

alloc_two.deallocate(test);

return 0;
}
17 changes: 17 additions & 0 deletions src/umpire/ResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,23 @@ util::AllocationRecord ResourceManager::deregisterAllocation(void* ptr)
return m_allocations.remove(ptr);
}

void* ResourceManager::transfer(void* ptr, Allocator to)
{
auto alloc_record = findAllocationRecord(ptr);

if (!(alloc_record->strategy->treatAsPassthrough() && to.getAllocationStrategy()->treatAsPassthrough())) {
Copy link
Member

Choose a reason for hiding this comment

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

So this does a direct transfer when the underlying allocators are the same, but moves when they are different? Wouldn't this allow a direct transfer between named allocators built on different base allocators? Should this take a resource to use for the copy?

return move(ptr, to);
} else {
Allocator from{alloc_record->strategy};
auto record = from.deregisterAllocation(ptr, alloc_record->strategy);

record.strategy = to.getAllocationStrategy();
to.registerAllocation(ptr, record.size, record.strategy);

return ptr;
}
}

const util::AllocationRecord* ResourceManager::findAllocationRecord(void* ptr) const
{
auto alloc_record = m_allocations.find(ptr);
Expand Down
8 changes: 8 additions & 0 deletions src/umpire/ResourceManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ class ResourceManager {
*/
util::AllocationRecord deregisterAllocation(void* ptr);

/*!
*
*
*
*
*/
void* transfer(void* ptr, Allocator to);

/*!
* \brief Find the allocation record associated with an address ptr.
*
Expand Down
35 changes: 35 additions & 0 deletions src/umpire/event/event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,45 @@
#include <utility>

#include "camp/camp.hpp"
#include "camp/resource.hpp"
#include "umpire/event/recorder_factory.hpp"
#include "umpire/util/Macros.hpp"

namespace camp {
namespace resources {
inline namespace v1 {

inline std::string to_string(camp::resources::Resource& r)
{
switch (r.get_platform()) {
case camp::resources::Platform::cuda:
return "camp::resource::Cuda";
break;
case camp::resources::Platform::hip:
return "camp::resource::Hip";
break;
case camp::resources::Platform::host:
return "camp::resource::Host";
break;
case camp::resources::Platform::omp_target:
return "camp::resource::OmpTarget";
break;
case camp::resources::Platform::sycl:
return "camp::resource::Sycl";
break;
case camp::resources::Platform::undefined:
return "camp::resource::Undefined";
}

return "unkown resource";
}

} // namespace v1
} // namespace resources
} // namespace camp

namespace umpire {

namespace event {

namespace {
Expand Down
5 changes: 5 additions & 0 deletions src/umpire/strategy/AllocationStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ bool AllocationStrategy::isTracked() const noexcept
return m_tracked;
}

bool AllocationStrategy::treatAsPassthrough() const noexcept
{
return false;
}

std::ostream& operator<<(std::ostream& os, const AllocationStrategy& strategy)
{
os << "[" << strategy.m_name << "," << strategy.m_id << "]";
Expand Down
2 changes: 2 additions & 0 deletions src/umpire/strategy/AllocationStrategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ class AllocationStrategy {

bool isTracked() const noexcept;

virtual bool treatAsPassthrough() const noexcept;

std::size_t m_current_size{0};
std::size_t m_high_watermark{0};
std::size_t m_allocation_count{0};
Expand Down
5 changes: 5 additions & 0 deletions src/umpire/strategy/NamedAllocationStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,10 @@ MemoryResourceTraits NamedAllocationStrategy::getTraits() const noexcept
return m_allocator->getTraits();
}

bool NamedAllocationStrategy::treatAsPassthrough() const noexcept
{
return true;
}

} // end of namespace strategy
} // end of namespace umpire
2 changes: 2 additions & 0 deletions src/umpire/strategy/NamedAllocationStrategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class NamedAllocationStrategy : public AllocationStrategy {

MemoryResourceTraits getTraits() const noexcept override;

bool treatAsPassthrough() const noexcept override;

protected:
strategy::AllocationStrategy* m_allocator;
};
Expand Down
39 changes: 39 additions & 0 deletions tests/integration/operation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,3 +836,42 @@ TEST(AsyncTest, Prefetch)
alloc.deallocate(array);
}
#endif

TEST(Transfer, Transfer)
{
auto& rm = umpire::ResourceManager::getInstance();

auto alloc_one = rm.makeAllocator<umpire::strategy::NamedAllocationStrategy>("transfer_one", rm.getAllocator("HOST"));
auto alloc_two = rm.makeAllocator<umpire::strategy::NamedAllocationStrategy>("transfer_two", rm.getAllocator("HOST"));

void* data = alloc_one.allocate(100);
void* xfer_data{nullptr};

ASSERT_NO_THROW(xfer_data = rm.transfer(data, alloc_two));

ASSERT_EQ(data, xfer_data);

ASSERT_NO_THROW(alloc_two.deallocate(xfer_data));
}

TEST(Transfer, Move)
{
auto& rm = umpire::ResourceManager::getInstance();

auto alloc_one = rm.makeAllocator<umpire::strategy::QuickPool>("transfer_three", rm.getAllocator("HOST"));
auto alloc_two =
rm.makeAllocator<umpire::strategy::NamedAllocationStrategy>("transfer_four", rm.getAllocator("HOST"));

void* xfer_data{nullptr};

void* data = alloc_one.allocate(100);
ASSERT_NO_THROW(xfer_data = rm.transfer(data, alloc_two));
ASSERT_NE(xfer_data, data);
ASSERT_NO_THROW(alloc_two.deallocate(xfer_data));

xfer_data = nullptr;
data = alloc_two.allocate(100);
ASSERT_NO_THROW(xfer_data = rm.transfer(data, alloc_one));
ASSERT_NE(xfer_data, data);
ASSERT_NO_THROW(alloc_one.deallocate(xfer_data));
}