Skip to content

[OpenMP][NFC] Move mapping related code into OpenMP/Mapping.cpp #75239

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

Merged
merged 1 commit into from
Dec 12, 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
1 change: 1 addition & 0 deletions openmp/libomptarget/include/ExclusiveAccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#ifndef OMPTARGET_EXCLUSIVE_ACCESS
#define OMPTARGET_EXCLUSIVE_ACCESS

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <mutex>
Expand Down
91 changes: 91 additions & 0 deletions openmp/libomptarget/include/OpenMP/Mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef OMPTARGET_OPENMP_MAPPING_H
#define OMPTARGET_OPENMP_MAPPING_H

#include "ExclusiveAccess.h"
#include "Shared/EnvironmentVar.h"
#include "omptarget.h"

Expand Down Expand Up @@ -443,4 +444,94 @@ int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
void **ArgMappers, AsyncInfoTy &AsyncInfo,
bool FromMapper = false);

struct MappingInfoTy {
MappingInfoTy(DeviceTy &Device) : Device(Device) {}

/// Host data to device map type with a wrapper key indirection that allows
/// concurrent modification of the entries without invalidating the underlying
/// entries.
using HostDataToTargetListTy =
std::set<HostDataToTargetMapKeyTy, std::less<>>;

/// The HDTTMap is a protected object that can only be accessed by one thread
/// at a time.
ProtectedObj<HostDataToTargetListTy> HostDataToTargetMap;

/// The type used to access the HDTT map.
using HDTTMapAccessorTy = decltype(HostDataToTargetMap)::AccessorTy;

/// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures
/// exclusive access to the HDTT map.
LookupResult lookupMapping(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
int64_t Size,
HostDataToTargetTy *OwnedTPR = nullptr);

/// Get the target pointer based on host pointer begin and base. If the
/// mapping already exists, the target pointer will be returned directly. In
/// addition, if required, the memory region pointed by \p HstPtrBegin of size
/// \p Size will also be transferred to the device. If the mapping doesn't
/// exist, and if unified shared memory is not enabled, a new mapping will be
/// created and the data will also be transferred accordingly. nullptr will be
/// returned because of any of following reasons:
/// - Data allocation failed;
/// - The user tried to do an illegal mapping;
/// - Data transfer issue fails.
TargetPointerResultTy getTargetPointer(
HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase,
int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName,
bool HasFlagTo, bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount,
bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier,
AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR = nullptr,
bool ReleaseHDTTMap = true);

/// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor
/// ensures exclusive access to the HDTT map.
void *getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
int64_t Size);

/// Return the target pointer begin (where the data will be moved).
/// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target.
/// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry
/// reference counters will be decremented.
/// - \p MustContain enforces that the query must not extend beyond an already
/// mapped entry to be valid.
/// - \p ForceDelete deletes the entry regardless of its reference counting
/// (unless it is infinite).
/// - \p FromDataEnd tracks the number of threads referencing the entry at
/// targetDataEnd for delayed deletion purpose.
[[nodiscard]] TargetPointerResultTy
getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool UpdateRefCount,
bool UseHoldRefCount, bool MustContain = false,
bool ForceDelete = false, bool FromDataEnd = false);

/// Remove the \p Entry from the data map. Expect the entry's total reference
/// count to be zero and the caller thread to be the last one using it. \p
/// HDTTMap ensure the caller holds exclusive access and can modify the map.
/// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c
/// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling
/// this function if the map entry is not expected to exist because \p
/// HstPtrBegin uses shared memory.
[[nodiscard]] int eraseMapEntry(HDTTMapAccessorTy &HDTTMap,
HostDataToTargetTy *Entry, int64_t Size);

/// Deallocate the \p Entry from the device memory and delete it. Return \c
/// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and
/// return \c OFFLOAD_FAIL otherwise.
[[nodiscard]] int deallocTgtPtrAndEntry(HostDataToTargetTy *Entry,
int64_t Size);

int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
int disassociatePtr(void *HstPtrBegin);

/// Print information about the transfer from \p HstPtr to \p TgtPtr (or vice
/// versa if \p H2D is false). If there is an existing mapping, or if \p Entry
/// is set, the associated metadata will be printed as well.
void printCopyInfo(void *TgtPtr, void *HstPtr, int64_t Size, bool H2D,
HostDataToTargetTy *Entry,
MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr);

private:
DeviceTy &Device;
};

#endif // OMPTARGET_OPENMP_MAPPING_H
96 changes: 15 additions & 81 deletions openmp/libomptarget/include/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,6 @@ struct DeviceTy {

bool HasMappedGlobalData = false;

/// Host data to device map type with a wrapper key indirection that allows
/// concurrent modification of the entries without invalidating the underlying
/// entries.
using HostDataToTargetListTy =
std::set<HostDataToTargetMapKeyTy, std::less<>>;

/// The HDTTMap is a protected object that can only be accessed by one thread
/// at a time.
ProtectedObj<HostDataToTargetListTy> HostDataToTargetMap;

/// The type used to access the HDTT map.
using HDTTMapAccessorTy = decltype(HostDataToTargetMap)::AccessorTy;

PendingCtorsDtorsPerLibrary PendingCtorsDtors;

std::mutex PendingGlobalsMtx;
Comment on lines 56 to 58
Copy link
Contributor

Choose a reason for hiding this comment

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

These are unused and only kept around for backwards compatibility with existing binaries.

Expand All @@ -80,71 +67,8 @@ struct DeviceTy {
/// Try to initialize the device and return any failure.
llvm::Error init();

// Return true if data can be copied to DstDevice directly
bool isDataExchangable(const DeviceTy &DstDevice);

/// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures
/// exclusive access to the HDTT map.
LookupResult lookupMapping(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
int64_t Size,
HostDataToTargetTy *OwnedTPR = nullptr);

/// Get the target pointer based on host pointer begin and base. If the
/// mapping already exists, the target pointer will be returned directly. In
/// addition, if required, the memory region pointed by \p HstPtrBegin of size
/// \p Size will also be transferred to the device. If the mapping doesn't
/// exist, and if unified shared memory is not enabled, a new mapping will be
/// created and the data will also be transferred accordingly. nullptr will be
/// returned because of any of following reasons:
/// - Data allocation failed;
/// - The user tried to do an illegal mapping;
/// - Data transfer issue fails.
TargetPointerResultTy getTargetPointer(
HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase,
int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName,
bool HasFlagTo, bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount,
bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier,
AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR = nullptr,
bool ReleaseHDTTMap = true);

/// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor
/// ensures exclusive access to the HDTT map.
void *getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
int64_t Size);

/// Return the target pointer begin (where the data will be moved).
/// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target.
/// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry
/// reference counters will be decremented.
/// - \p MustContain enforces that the query must not extend beyond an already
/// mapped entry to be valid.
/// - \p ForceDelete deletes the entry regardless of its reference counting
/// (unless it is infinite).
/// - \p FromDataEnd tracks the number of threads referencing the entry at
/// targetDataEnd for delayed deletion purpose.
[[nodiscard]] TargetPointerResultTy
getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool UpdateRefCount,
bool UseHoldRefCount, bool MustContain = false,
bool ForceDelete = false, bool FromDataEnd = false);

/// Remove the \p Entry from the data map. Expect the entry's total reference
/// count to be zero and the caller thread to be the last one using it. \p
/// HDTTMap ensure the caller holds exclusive access and can modify the map.
/// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c
/// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling
/// this function if the map entry is not expected to exist because \p
/// HstPtrBegin uses shared memory.
[[nodiscard]] int eraseMapEntry(HDTTMapAccessorTy &HDTTMap,
HostDataToTargetTy *Entry, int64_t Size);

/// Deallocate the \p Entry from the device memory and delete it. Return \c
/// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and
/// return \c OFFLOAD_FAIL otherwise.
[[nodiscard]] int deallocTgtPtrAndEntry(HostDataToTargetTy *Entry,
int64_t Size);

int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
int disassociatePtr(void *HstPtrBegin);
/// Provide access to the mapping handler.
MappingInfoTy &getMappingInfo() { return MappingInfo; }

__tgt_target_table *loadBinary(__tgt_device_image *Img);

Expand All @@ -159,6 +83,7 @@ struct DeviceTy {
/// be used (host, shared, device).
void *allocData(int64_t Size, void *HstPtr = nullptr,
int32_t Kind = TARGET_ALLOC_DEFAULT);

/// Deallocates memory which \p TgtPtrBegin points at and returns
/// OFFLOAD_SUCCESS/OFFLOAD_FAIL when succeeds/fails. p Kind dictates what
/// allocator should be used (host, shared, device).
Expand All @@ -170,12 +95,16 @@ struct DeviceTy {
int32_t submitData(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size,
AsyncInfoTy &AsyncInfo,
HostDataToTargetTy *Entry = nullptr,
DeviceTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);

// Copy data from device back to host
int32_t retrieveData(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size,
AsyncInfoTy &AsyncInfo,
HostDataToTargetTy *Entry = nullptr,
DeviceTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);

// Return true if data can be copied to DstDevice directly
bool isDataExchangable(const DeviceTy &DstDevice);

// Copy data from current device to destination device directly
int32_t dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr,
Expand Down Expand Up @@ -240,7 +169,12 @@ struct DeviceTy {
void deinit();

/// All offload entries available on this device.
llvm::DenseMap<llvm::StringRef, OffloadEntryTy *> DeviceOffloadEntries;
using DeviceOffloadEntriesMapTy =
llvm::DenseMap<llvm::StringRef, OffloadEntryTy *>;
ProtectedObj<DeviceOffloadEntriesMapTy> DeviceOffloadEntries;

/// Handler to collect and organize host-2-device mapping information.
MappingInfoTy MappingInfo;
};

#endif
19 changes: 10 additions & 9 deletions openmp/libomptarget/src/OpenMP/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ EXTERN int omp_target_is_present(const void *Ptr, int DeviceNum) {
// only check 1 byte. Cannot set size 0 which checks whether the pointer (zero
// lengh array) is mapped instead of the referred storage.
TargetPointerResultTy TPR =
DeviceOrErr->getTgtPtrBegin(const_cast<void *>(Ptr), 1,
/*UpdateRefCount=*/false,
/*UseHoldRefCount=*/false);
DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1,
/*UpdateRefCount=*/false,
/*UseHoldRefCount=*/false);
int Rc = TPR.isPresent();
DP("Call to omp_target_is_present returns %d\n", Rc);
return Rc;
Expand Down Expand Up @@ -544,8 +544,8 @@ EXTERN int omp_target_associate_ptr(const void *HostPtr, const void *DevicePtr,
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

void *DeviceAddr = (void *)((uint64_t)DevicePtr + (uint64_t)DeviceOffset);
int Rc = DeviceOrErr->associatePtr(const_cast<void *>(HostPtr),
const_cast<void *>(DeviceAddr), Size);
int Rc = DeviceOrErr->getMappingInfo().associatePtr(
const_cast<void *>(HostPtr), const_cast<void *>(DeviceAddr), Size);
DP("omp_target_associate_ptr returns %d\n", Rc);
return Rc;
}
Expand All @@ -571,7 +571,8 @@ EXTERN int omp_target_disassociate_ptr(const void *HostPtr, int DeviceNum) {
if (!DeviceOrErr)
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

int Rc = DeviceOrErr->disassociatePtr(const_cast<void *>(HostPtr));
int Rc = DeviceOrErr->getMappingInfo().disassociatePtr(
const_cast<void *>(HostPtr));
DP("omp_target_disassociate_ptr returns %d\n", Rc);
return Rc;
}
Expand Down Expand Up @@ -603,9 +604,9 @@ EXTERN void *omp_get_mapped_ptr(const void *Ptr, int DeviceNum) {
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

TargetPointerResultTy TPR =
DeviceOrErr->getTgtPtrBegin(const_cast<void *>(Ptr), 1,
/*UpdateRefCount=*/false,
/*UseHoldRefCount=*/false);
DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1,
/*UpdateRefCount=*/false,
/*UseHoldRefCount=*/false);
if (!TPR.isPresent()) {
DP("Ptr " DPxMOD "is not present on device %d, returning nullptr.\n",
DPxPTR(Ptr), DeviceNum);
Expand Down
Loading