blob: d665575645036e43e0a8e3f9fa463a224f9f3238 [file] [log] [blame]
//===-- 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