| //===-- HostPlatformDevice.h - HostPlatformDevice class ---------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// Declaration of the HostPlatformDevice class. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef STREAMEXECUTOR_PLATFORMS_HOST_HOSTPLATFORMDEVICE_H |
| #define STREAMEXECUTOR_PLATFORMS_HOST_HOSTPLATFORMDEVICE_H |
| |
| #include <cstdlib> |
| #include <cstring> |
| |
| #include "streamexecutor/PlatformDevice.h" |
| |
| namespace streamexecutor { |
| namespace host { |
| |
| /// A concrete PlatformDevice subclass that performs its work on the host rather |
| /// than offloading to an accelerator. |
| class HostPlatformDevice : public PlatformDevice { |
| public: |
| std::string getName() const override { return "host"; } |
| |
| std::string getPlatformName() const override { return "host"; } |
| |
| Expected<const void *> |
| createKernel(const MultiKernelLoaderSpec &Spec) override { |
| if (!Spec.hasHostFunction()) { |
| return make_error("no host implementation available for kernel " + |
| Spec.getKernelName()); |
| } |
| return static_cast<const void *>(&Spec.getHostFunction()); |
| } |
| |
| Error destroyKernel(const void *Handle) override { return Error::success(); } |
| |
| Expected<const void *> createStream() override { |
| // TODO(jhen): Do something with threads to allow multiple streams. |
| return this; |
| } |
| |
| Error destroyStream(const void *Handle) override { return Error::success(); } |
| |
| Error launch(const void *PlatformStreamHandle, BlockDimensions BlockSize, |
| GridDimensions GridSize, const void *PKernelHandle, |
| const PackedKernelArgumentArrayBase &ArgumentArray) override { |
| // TODO(jhen): Can we do something with BlockSize and GridSize? |
| if (!(BlockSize.X == 1 && BlockSize.Y == 1 && BlockSize.Z == 1)) { |
| return make_error( |
| "Block dimensions were (" + llvm::Twine(BlockSize.X) + "," + |
| llvm::Twine(BlockSize.Y) + "," + llvm::Twine(BlockSize.Z) + |
| "), but only size (1,1,1) is permitted for this platform"); |
| } |
| if (!(GridSize.X == 1 && GridSize.Y == 1 && GridSize.Z == 1)) { |
| return make_error( |
| "Grid dimensions were (" + llvm::Twine(GridSize.X) + "," + |
| llvm::Twine(GridSize.Y) + "," + llvm::Twine(GridSize.Z) + |
| "), but only size (1,1,1) is permitted for this platform"); |
| } |
| |
| (*static_cast<const std::function<void(const void *const *)> *>( |
| PKernelHandle))(ArgumentArray.getAddresses()); |
| return Error::success(); |
| } |
| |
| Error copyD2H(const void *PlatformStreamHandle, const void *DeviceSrcHandle, |
| size_t SrcByteOffset, void *HostDst, size_t DstByteOffset, |
| size_t ByteCount) override { |
| std::memcpy(offset(HostDst, DstByteOffset), |
| offset(DeviceSrcHandle, SrcByteOffset), ByteCount); |
| return Error::success(); |
| } |
| |
| Error copyH2D(const void *PlatformStreamHandle, const void *HostSrc, |
| size_t SrcByteOffset, const void *DeviceDstHandle, |
| size_t DstByteOffset, size_t ByteCount) override { |
| std::memcpy(offset(DeviceDstHandle, DstByteOffset), |
| offset(HostSrc, SrcByteOffset), ByteCount); |
| return Error::success(); |
| } |
| |
| Error copyD2D(const void *PlatformStreamHandle, const void *DeviceSrcHandle, |
| size_t SrcByteOffset, const void *DeviceDstHandle, |
| size_t DstByteOffset, size_t ByteCount) override { |
| std::memcpy(offset(DeviceDstHandle, DstByteOffset), |
| offset(DeviceSrcHandle, SrcByteOffset), ByteCount); |
| return Error::success(); |
| } |
| |
| Error blockHostUntilDone(const void *PlatformStreamHandle) override { |
| // All host operations are synchronous anyway. |
| return Error::success(); |
| } |
| |
| Expected<void *> allocateDeviceMemory(size_t ByteCount) override { |
| return std::malloc(ByteCount); |
| } |
| |
| Error freeDeviceMemory(const void *Handle) override { |
| std::free(const_cast<void *>(Handle)); |
| return Error::success(); |
| } |
| |
| Error registerHostMemory(void *Memory, size_t ByteCount) override { |
| return Error::success(); |
| } |
| |
| Error unregisterHostMemory(const void *Memory) override { |
| return Error::success(); |
| } |
| |
| Error synchronousCopyD2H(const void *DeviceSrcHandle, size_t SrcByteOffset, |
| void *HostDst, size_t DstByteOffset, |
| size_t ByteCount) override { |
| std::memcpy(offset(HostDst, DstByteOffset), |
| offset(DeviceSrcHandle, SrcByteOffset), ByteCount); |
| return Error::success(); |
| } |
| |
| Error synchronousCopyH2D(const void *HostSrc, size_t SrcByteOffset, |
| const void *DeviceDstHandle, size_t DstByteOffset, |
| size_t ByteCount) override { |
| std::memcpy(offset(DeviceDstHandle, DstByteOffset), |
| offset(HostSrc, SrcByteOffset), ByteCount); |
| return Error::success(); |
| } |
| |
| Error synchronousCopyD2D(const void *DeviceSrcHandle, size_t SrcByteOffset, |
| const void *DeviceDstHandle, size_t DstByteOffset, |
| size_t ByteCount) override { |
| std::memcpy(offset(DeviceDstHandle, DstByteOffset), |
| offset(DeviceSrcHandle, SrcByteOffset), ByteCount); |
| return Error::success(); |
| } |
| |
| /// Gets the value at the given index from a GlobalDeviceMemory<T> instance |
| /// created by this class. |
| template <typename T> |
| static T getDeviceValue(const streamexecutor::GlobalDeviceMemory<T> &Memory, |
| size_t Index) { |
| return static_cast<const T *>(Memory.getHandle())[Index]; |
| } |
| |
| private: |
| static void *offset(const void *Base, size_t Offset) { |
| return const_cast<char *>(static_cast<const char *>(Base) + Offset); |
| } |
| }; |
| |
| } // namespace host |
| } // namespace streamexecutor |
| |
| #endif // STREAMEXECUTOR_PLATFORMS_HOST_HOSTPLATFORMDEVICE_H |