Skip to content

Commit

Permalink
[SYCL] Implement initial device_global registration (#5499)
Browse files Browse the repository at this point in the history
These changes add required interface for the integration footer to register the `device_global` of a program as well as reading the
extended information supplied by sycl-post-link through the "SYCL/device globals" property. The information is stored in a map
managed by the program manager.

Note that this is the first change to the runtime relating to `device_global` and as such the feature is not complete nor fully testable. It simply intents to add an interface for the integration footer as well as a consumer for the information sycl-post-link will be generating when future work is added.

See [sycl/doc/DeviceGlobal.md](https://github.com/intel/llvm/blob/sycl/sycl/doc/DeviceGlobal.md).
  • Loading branch information
steffenlarsen committed Feb 10, 2022
1 parent c536e76 commit 5931af5
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 0 deletions.
21 changes: 21 additions & 0 deletions sycl/include/CL/sycl/detail/device_global_map.hpp
@@ -0,0 +1,21 @@
//==-------------------- device_global_map.hpp -----------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#pragma once

__SYCL_INLINE_NAMESPACE(cl) {
namespace sycl {
namespace detail {
namespace device_global_map {

void add(void *DeviceGlobalPtr, const char *UniqueId);

} // namespace device_global_map
} // namespace detail
} // namespace sycl
} // __SYCL_INLINE_NAMESPACE(cl)
2 changes: 2 additions & 0 deletions sycl/include/CL/sycl/detail/pi.h
Expand Up @@ -751,6 +751,8 @@ static const uint8_t PI_DEVICE_BINARY_OFFLOAD_KIND_SYCL = 4;
#define __SYCL_PI_PROPERTY_SET_SYCL_ASSERT_USED "SYCL/assert used"
/// PropertySetRegistry::SYCL_EXPORTED_SYMBOLS defined in PropertySetIO.h
#define __SYCL_PI_PROPERTY_SET_SYCL_EXPORTED_SYMBOLS "SYCL/exported symbols"
/// PropertySetRegistry::SYCL_DEVICE_GLOBALS defined in PropertySetIO.h
#define __SYCL_PI_PROPERTY_SET_SYCL_DEVICE_GLOBALS "SYCL/device globals"

/// Program metadata tags recognized by the PI backends. For kernels the tag
/// must appear after the kernel name.
Expand Down
7 changes: 7 additions & 0 deletions sycl/include/CL/sycl/detail/pi.hpp
Expand Up @@ -376,6 +376,13 @@ class DeviceBinaryImage {
ExportedSymbols.init(Bin, __SYCL_PI_PROPERTY_SET_SYCL_EXPORTED_SYMBOLS);
return ExportedSymbols;
}
const PropertyRange getDeviceGlobals() const {
// We can't have this variable as a class member, since it would break
// the ABI backwards compatibility.
DeviceBinaryImage::PropertyRange DeviceGlobals;
DeviceGlobals.init(Bin, __SYCL_PI_PROPERTY_SET_SYCL_DEVICE_GLOBALS);
return DeviceGlobals;
}
virtual ~DeviceBinaryImage() {}

protected:
Expand Down
1 change: 1 addition & 0 deletions sycl/source/CMakeLists.txt
Expand Up @@ -134,6 +134,7 @@ set(SYCL_SOURCES
"detail/context_impl.cpp"
"detail/device_binary_image.cpp"
"detail/device_filter.cpp"
"detail/device_global_map.cpp"
"detail/device_impl.cpp"
"detail/error_handling/enqueue_kernel.cpp"
"detail/event_impl.cpp"
Expand Down
24 changes: 24 additions & 0 deletions sycl/source/detail/device_global_map.cpp
@@ -0,0 +1,24 @@
//==-------------------- device_global_map.cpp -----------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <detail/program_manager/program_manager.hpp>

__SYCL_INLINE_NAMESPACE(cl) {
namespace sycl {
namespace detail {
namespace device_global_map {

void add(void *DeviceGlobalPtr, const char *UniqueId) {
detail::ProgramManager::getInstance().addDeviceGlobalEntry(DeviceGlobalPtr,
UniqueId);
}

} // namespace device_global_map
} // namespace detail
} // namespace sycl
} // __SYCL_INLINE_NAMESPACE(cl)
51 changes: 51 additions & 0 deletions sycl/source/detail/device_global_map_entry.hpp
@@ -0,0 +1,51 @@
//==----------------- device_global_map_entry.hpp --------------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#pragma once

#include <cstdint>
#include <unordered_map>

__SYCL_INLINE_NAMESPACE(cl) {
namespace sycl {
namespace detail {

// Forward declaration
class device_impl;

struct DeviceGlobalMapEntry {
// Pointer to the device_global on host.
void *MDeviceGlobalPtr;
// Size of the underlying type in the device_global.
std::uint32_t MDeviceGlobalTSize;
// True if the device_global has been decorated with device_image_scope
bool MIsDeviceImageScopeDecorated;
// Map between devices and corresponding USM allocations for the
// device_global. This should always be empty if MIsDeviceImageScopeDecorated
// is true.
std::unordered_map<std::shared_ptr<device_impl>, void *> MDeviceToUSMPtrMap;

// Constructor only initializes with the pointer to the device_global as the
// additional information is loaded after.
DeviceGlobalMapEntry(void *DeviceGlobalPtr)
: MDeviceGlobalPtr(DeviceGlobalPtr), MDeviceGlobalTSize(0),
MIsDeviceImageScopeDecorated(false) {}

void initialize(std::uint32_t DeviceGlobalTSize,
bool IsDeviceImageScopeDecorated) {
assert(DeviceGlobalTSize != 0 && "Device global initialized with 0 size.");
assert(MDeviceGlobalTSize == 0 &&
"Device global has already been initialized.");
MDeviceGlobalTSize = DeviceGlobalTSize;
MIsDeviceImageScopeDecorated = IsDeviceImageScopeDecorated;
}
};

} // namespace detail
} // namespace sycl
} // __SYCL_INLINE_NAMESPACE(cl)
35 changes: 35 additions & 0 deletions sycl/source/detail/program_manager/program_manager.cpp
Expand Up @@ -1130,6 +1130,32 @@ void ProgramManager::addImages(pi_device_binaries DeviceBinary) {
std::make_pair(EntriesIt->name, std::move(KernelID)));
}
}
// ... and initialize associated device_global information
{
std::lock_guard<std::mutex> DeviceGlobalsGuard(m_DeviceGlobalsMutex);

auto DeviceGlobals = Img->getDeviceGlobals();
for (const pi_device_binary_property &DeviceGlobal : DeviceGlobals) {
auto Entry = m_DeviceGlobals.find(DeviceGlobal->Name);
assert(Entry != m_DeviceGlobals.end() &&
"Device global has not been registered.");

pi::ByteArray DeviceGlobalInfo =
pi::DeviceBinaryProperty(DeviceGlobal).asByteArray();

// The supplied device_global info property is expected to contain:
// * 8 bytes - Size of the property.
// * 4 bytes - Size of the underlying type in the device_global.
// * 1 byte - 0 if device_global has device_image_scope and any value
// otherwise.
// Note: Property may be padded.
assert(DeviceGlobalInfo.size() >= 13 && "Unexpected property size");
const std::uint32_t TypeSize =
*reinterpret_cast<const std::uint32_t *>(&DeviceGlobalInfo[8]);
const std::uint32_t DeviceImageScopeDecorated = DeviceGlobalInfo[12];
Entry->second.initialize(TypeSize, DeviceImageScopeDecorated);
}
}
m_DeviceImages[KSId].reset(new std::vector<RTDeviceBinaryImageUPtr>());

cacheKernelUsesAssertInfo(M, *Img);
Expand Down Expand Up @@ -1379,6 +1405,15 @@ kernel_id ProgramManager::getBuiltInKernelID(const std::string &KernelName) {
return KernelID->second;
}

void ProgramManager::addDeviceGlobalEntry(void *DeviceGlobalPtr,
const char *UniqueId) {
std::lock_guard<std::mutex> DeviceGlobalsGuard(m_DeviceGlobalsMutex);

assert(m_DeviceGlobals.find(UniqueId) == m_DeviceGlobals.end() &&
"Device global has already been registered.");
m_DeviceGlobals.insert({UniqueId, DeviceGlobalMapEntry(DeviceGlobalPtr)});
}

std::vector<device_image_plain>
ProgramManager::getSYCLDeviceImagesWithCompatibleState(
const context &Ctx, const std::vector<device> &Devs,
Expand Down
10 changes: 10 additions & 0 deletions sycl/source/detail/program_manager/program_manager.hpp
Expand Up @@ -16,6 +16,7 @@
#include <CL/sycl/device.hpp>
#include <CL/sycl/kernel_bundle.hpp>
#include <CL/sycl/stl.hpp>
#include <detail/device_global_map_entry.hpp>
#include <detail/spec_constant_impl.hpp>

#include <cstdint>
Expand Down Expand Up @@ -182,6 +183,9 @@ class ProgramManager {
// built-in kernel name.
kernel_id getBuiltInKernelID(const std::string &KernelName);

// The function inserts a device_global entry into the device_global map.
void addDeviceGlobalEntry(void *DeviceGlobalPtr, const char *UniqueId);

// The function returns a vector of SYCL device images that are compiled with
// the required state and at least one device from the passed list of devices.
std::vector<device_image_plain>
Expand Down Expand Up @@ -367,6 +371,12 @@ class ProgramManager {

using KernelNameWithOSModule = std::pair<std::string, OSModuleHandle>;
std::set<KernelNameWithOSModule> m_KernelUsesAssert;

// Map between device_global unique ids and associated information.
std::unordered_map<std::string, DeviceGlobalMapEntry> m_DeviceGlobals;

/// Protects m_DeviceGlobals.
std::mutex m_DeviceGlobalsMutex;
};
} // namespace detail
} // namespace sycl
Expand Down

0 comments on commit 5931af5

Please sign in to comment.