CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
144 lines
5.0 KiB
C++
144 lines
5.0 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file contains the definition of the DeviceContext class, which serves
|
|
/// as the high-level interface to a particular device (GPU).
|
|
///
|
|
/// This class provides methods for allocating buffers, loading binaries, and
|
|
/// getting and launching kernels on the device.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MATHTEST_DEVICECONTEXT_HPP
|
|
#define MATHTEST_DEVICECONTEXT_HPP
|
|
|
|
#include "mathtest/DeviceResources.hpp"
|
|
#include "mathtest/ErrorHandling.hpp"
|
|
#include "mathtest/Support.hpp"
|
|
|
|
#include "llvm/ADT/SetVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
namespace mathtest {
|
|
|
|
const llvm::SetVector<llvm::StringRef> &getPlatforms();
|
|
|
|
namespace detail {
|
|
|
|
void allocManagedMemory(ol_device_handle_t DeviceHandle, std::size_t Size,
|
|
void **AllocationOut) noexcept;
|
|
} // namespace detail
|
|
|
|
class DeviceContext {
|
|
// For simplicity, the current design of this class doesn't have support for
|
|
// asynchronous operations and all types of memory allocation.
|
|
//
|
|
// Other use cases could benefit from operations like enqueued kernel launch
|
|
// and enqueued memcpy, as well as device and host memory allocation.
|
|
|
|
public:
|
|
explicit DeviceContext(std::size_t GlobalDeviceId = 0);
|
|
|
|
explicit DeviceContext(llvm::StringRef Platform, std::size_t DeviceId = 0);
|
|
|
|
template <typename T>
|
|
ManagedBuffer<T> createManagedBuffer(std::size_t Size) const noexcept {
|
|
void *UntypedAddress = nullptr;
|
|
|
|
detail::allocManagedMemory(DeviceHandle, Size * sizeof(T), &UntypedAddress);
|
|
T *TypedAddress = static_cast<T *>(UntypedAddress);
|
|
|
|
return ManagedBuffer<T>(TypedAddress, Size);
|
|
}
|
|
|
|
[[nodiscard]] llvm::Expected<std::shared_ptr<DeviceImage>>
|
|
loadBinary(llvm::StringRef Directory, llvm::StringRef BinaryName) const;
|
|
|
|
template <typename KernelSignature>
|
|
[[nodiscard]] llvm::Expected<DeviceKernel<KernelSignature>>
|
|
getKernel(const std::shared_ptr<DeviceImage> &Image,
|
|
llvm::StringRef KernelName) const {
|
|
assert(Image && "Image provided to getKernel is null");
|
|
|
|
if (Image->DeviceHandle != DeviceHandle)
|
|
return llvm::createStringError(
|
|
"Image provided to getKernel was created for a different device");
|
|
|
|
auto ExpectedHandle = getKernelHandle(Image->Handle, KernelName);
|
|
|
|
if (!ExpectedHandle)
|
|
return ExpectedHandle.takeError();
|
|
|
|
return DeviceKernel<KernelSignature>(Image, *ExpectedHandle);
|
|
}
|
|
|
|
template <typename KernelSignature, typename... ArgTypes>
|
|
void launchKernel(DeviceKernel<KernelSignature> Kernel, uint32_t NumGroups,
|
|
uint32_t GroupSize, ArgTypes &&...Args) const noexcept {
|
|
using ExpectedTypes =
|
|
typename FunctionTypeTraits<KernelSignature>::ArgTypesTuple;
|
|
using ProvidedTypes = std::tuple<std::decay_t<ArgTypes>...>;
|
|
|
|
static_assert(std::is_same_v<ExpectedTypes, ProvidedTypes>,
|
|
"Argument types provided to launchKernel do not match the "
|
|
"kernel's signature");
|
|
|
|
if (Kernel.Image->DeviceHandle != DeviceHandle)
|
|
FATAL_ERROR("Kernel provided to launchKernel was created for a different "
|
|
"device");
|
|
|
|
if constexpr (sizeof...(Args) == 0) {
|
|
launchKernelImpl(Kernel.Handle, NumGroups, GroupSize, 0, nullptr,
|
|
nullptr);
|
|
} else {
|
|
static_assert(
|
|
(std::is_trivially_copyable_v<std::decay_t<ArgTypes>> && ...),
|
|
"Argument types provided to launchKernel must be trivially copyable");
|
|
|
|
ProvidedTypes ArgsTuple(std::forward<ArgTypes>(Args)...);
|
|
std::apply(
|
|
[&](auto &...A) {
|
|
void *ArgPtrs[] = {static_cast<void *>(&A)...};
|
|
size_t ArgSizes[] = {sizeof(A)...};
|
|
launchKernelImpl(Kernel.Handle, NumGroups, GroupSize,
|
|
sizeof...(Args), ArgPtrs, ArgSizes);
|
|
},
|
|
ArgsTuple);
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] llvm::StringRef getName() const noexcept;
|
|
|
|
[[nodiscard]] llvm::StringRef getPlatform() const noexcept;
|
|
|
|
private:
|
|
[[nodiscard]] llvm::Expected<ol_symbol_handle_t>
|
|
getKernelHandle(ol_program_handle_t ProgramHandle,
|
|
llvm::StringRef KernelName) const noexcept;
|
|
|
|
void launchKernelImpl(ol_symbol_handle_t KernelHandle, uint32_t NumGroups,
|
|
uint32_t GroupSize, size_t NumArgs, void **ArgPtrs,
|
|
const size_t *ArgSizes) const noexcept;
|
|
|
|
std::size_t GlobalDeviceId;
|
|
ol_device_handle_t DeviceHandle;
|
|
};
|
|
} // namespace mathtest
|
|
|
|
#endif // MATHTEST_DEVICECONTEXT_HPP
|