diff options
author | Cedric Nugteren <web@cedricnugteren.nl> | 2017-10-28 17:32:37 +0200 |
---|---|---|
committer | Cedric Nugteren <web@cedricnugteren.nl> | 2017-10-28 17:32:37 +0200 |
commit | 12b08ae49154379f7471a40809ace6418857b387 (patch) | |
tree | ef958197db0bb8a67c9a5840f828b3f6c72bd8fc /src/clpp11.hpp | |
parent | 2949e156f5bfdd724987e67477da3e3608e4aaf9 (diff) | |
parent | fa6e5e67f585b77d34c3031c176de9a0f7904aa9 (diff) |
Merge branch 'master' into android_support
Diffstat (limited to 'src/clpp11.hpp')
-rw-r--r-- | src/clpp11.hpp | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/src/clpp11.hpp b/src/clpp11.hpp index 9e3a6b7f..0cdd92e7 100644 --- a/src/clpp11.hpp +++ b/src/clpp11.hpp @@ -60,34 +60,36 @@ namespace clblast { // ================================================================================================= // Represents a runtime error returned by an OpenCL API function -class CLError : public ErrorCode<DeviceError, cl_int> { +class CLCudaAPIError : public ErrorCode<DeviceError, cl_int> { public: - explicit CLError(cl_int status, const std::string &where): - ErrorCode(status, - where, - "OpenCL error: " + where + ": " + std::to_string(static_cast<int>(status))) { + explicit CLCudaAPIError(cl_int status, const std::string &where): + ErrorCode(status, where, "OpenCL error: " + where + ": " + + std::to_string(static_cast<int>(status))) { } static void Check(const cl_int status, const std::string &where) { if (status != CL_SUCCESS) { - throw CLError(status, where); + throw CLCudaAPIError(status, where); } } static void CheckDtor(const cl_int status, const std::string &where) { if (status != CL_SUCCESS) { - fprintf(stderr, "CLBlast: %s (ignoring)\n", CLError(status, where).what()); + fprintf(stderr, "CLBlast: %s (ignoring)\n", CLCudaAPIError(status, where).what()); } } }; +// Exception returned when building a program +using CLCudaAPIBuildError = CLCudaAPIError; + // ================================================================================================= // Error occurred in OpenCL -#define CheckError(call) CLError::Check(call, CLError::TrimCallString(#call)) +#define CheckError(call) CLCudaAPIError::Check(call, CLCudaAPIError::TrimCallString(#call)) -// Error occured in OpenCL (no-exception version for destructors) -#define CheckErrorDtor(call) CLError::CheckDtor(call, CLError::TrimCallString(#call)) +// Error occurred in OpenCL (no-exception version for destructors) +#define CheckErrorDtor(call) CLCudaAPIError::CheckDtor(call, CLCudaAPIError::TrimCallString(#call)) // ================================================================================================= @@ -143,6 +145,9 @@ using EventPointer = cl_event*; // ================================================================================================= +// Raw platform ID type +using RawPlatformID = cl_platform_id; + // C++11 version of 'cl_platform_id' class Platform { public: @@ -178,7 +183,7 @@ class Platform { } // Accessor to the private data-member - const cl_platform_id& operator()() const { return platform_; } + const RawPlatformID& operator()() const { return platform_; } private: cl_platform_id platform_; @@ -207,6 +212,9 @@ inline std::vector<Platform> GetAllPlatforms() { // ================================================================================================= +// Raw device ID type +using RawDeviceID = cl_device_id; + // C++11 version of 'cl_device_id' class Device { public: @@ -231,7 +239,7 @@ class Device { } // Methods to retrieve device information - cl_platform_id Platform() const { return GetInfo<cl_platform_id>(CL_DEVICE_PLATFORM); } + RawPlatformID PlatformID() const { return GetInfo<cl_platform_id>(CL_DEVICE_PLATFORM); } std::string Version() const { return GetInfoString(CL_DEVICE_VERSION); } size_t VersionNumber() const { @@ -263,11 +271,19 @@ class Device { unsigned long LocalMemSize() const { return static_cast<unsigned long>(GetInfo<cl_ulong>(CL_DEVICE_LOCAL_MEM_SIZE)); } + std::string Capabilities() const { return GetInfoString(CL_DEVICE_EXTENSIONS); } bool HasExtension(const std::string &extension) const { const auto extensions = Capabilities(); return extensions.find(extension) != std::string::npos; } + bool SupportsFP64() const { + return HasExtension("cl_khr_fp64"); + } + bool SupportsFP16() const { + if (Name() == "Mali-T628") { return true; } // supports fp16 but not cl_khr_fp16 officially + return HasExtension("cl_khr_fp16"); + } size_t CoreClock() const { return static_cast<size_t>(GetInfo<cl_uint>(CL_DEVICE_MAX_CLOCK_FREQUENCY)); @@ -331,9 +347,8 @@ class Device { std::string{"."} + std::to_string(GetInfo<cl_uint>(CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV)); } - // Accessor to the private data-member - const cl_device_id& operator()() const { return device_; } + const RawDeviceID& operator()() const { return device_; } private: cl_device_id device_; @@ -367,6 +382,9 @@ class Device { // ================================================================================================= +// Raw context type +using RawContext = cl_context; + // C++11 version of 'cl_context' class Context { public: @@ -386,12 +404,12 @@ class Context { auto status = CL_SUCCESS; const cl_device_id dev = device(); *context_ = clCreateContext(nullptr, 1, &dev, nullptr, nullptr, &status); - CLError::Check(status, "clCreateContext"); + CLCudaAPIError::Check(status, "clCreateContext"); } // Accessor to the private data-member - const cl_context& operator()() const { return *context_; } - cl_context* pointer() const { return &(*context_); } + const RawContext& operator()() const { return *context_; } + RawContext* pointer() const { return &(*context_); } private: std::shared_ptr<cl_context> context_; }; @@ -401,9 +419,6 @@ using ContextPointer = cl_context*; // ================================================================================================= -// Enumeration of build statuses of the run-time compilation process -enum class BuildStatus { kSuccess, kError, kInvalid }; - // C++11 version of 'cl_program'. class Program { public: @@ -416,10 +431,10 @@ class Program { delete p; }) { const char *source_ptr = &source[0]; - size_t length = source.length(); + const auto length = source.length(); auto status = CL_SUCCESS; *program_ = clCreateProgramWithSource(context(), 1, &source_ptr, &length, &status); - CLError::Check(status, "clCreateProgramWithSource"); + CLCudaAPIError::Check(status, "clCreateProgramWithSource"); } // Binary-based constructor with memory management @@ -429,18 +444,18 @@ class Program { delete p; }) { const char *binary_ptr = &binary[0]; - size_t length = binary.length(); + const auto length = binary.length(); auto status1 = CL_SUCCESS; auto status2 = CL_SUCCESS; - const cl_device_id dev = device(); + const auto dev = device(); *program_ = clCreateProgramWithBinary(context(), 1, &dev, &length, reinterpret_cast<const unsigned char**>(&binary_ptr), &status1, &status2); - CLError::Check(status1, "clCreateProgramWithBinary (binary status)"); - CLError::Check(status2, "clCreateProgramWithBinary"); + CLCudaAPIError::Check(status1, "clCreateProgramWithBinary (binary status)"); + CLCudaAPIError::Check(status2, "clCreateProgramWithBinary"); } - // Compiles the device program and returns whether or not there where any warnings/errors + // Compiles the device program and checks whether or not there are any warnings/errors void Build(const Device &device, std::vector<std::string> &options) { options.push_back("-cl-std=CL1.1"); auto options_string = std::accumulate(options.begin(), options.end(), std::string{" "}); @@ -448,6 +463,11 @@ class Program { CheckError(clBuildProgram(*program_, 1, &dev, options_string.c_str(), nullptr, nullptr)); } + // Confirms whether a certain status code is an actual compilation error or warning + bool StatusIsCompilationWarningOrError(const cl_int status) const { + return (status == CL_BUILD_PROGRAM_FAILURE); + } + // Retrieves the warning/error message from the compiler (if any) std::string GetBuildInfo(const Device &device) const { auto bytes = size_t{0}; @@ -478,6 +498,9 @@ class Program { // ================================================================================================= +// Raw command-queue type +using RawCommandQueue = cl_command_queue; + // C++11 version of 'cl_command_queue' class Queue { public: @@ -496,7 +519,7 @@ class Queue { }) { auto status = CL_SUCCESS; *queue_ = clCreateCommandQueue(context(), device(), CL_QUEUE_PROFILING_ENABLE, &status); - CLError::Check(status, "clCreateCommandQueue"); + CLCudaAPIError::Check(status, "clCreateCommandQueue"); } // Synchronizes the queue @@ -524,7 +547,7 @@ class Queue { } // Accessor to the private data-member - const cl_command_queue& operator()() const { return *queue_; } + const RawCommandQueue& operator()() const { return *queue_; } private: std::shared_ptr<cl_command_queue> queue_; }; @@ -588,7 +611,7 @@ class Buffer { if (access_ == BufferAccess::kWriteOnly) { flags = CL_MEM_WRITE_ONLY; } auto status = CL_SUCCESS; *buffer_ = clCreateBuffer(context(), flags, size*sizeof(T), nullptr, &status); - CLError::Check(status, "clCreateBuffer"); + CLCudaAPIError::Check(status, "clCreateBuffer"); } // As above, but now with read/write access as a default @@ -646,6 +669,9 @@ class Buffer { // Copies from host to device: writing the device buffer a-synchronously void WriteAsync(const Queue &queue, const size_t size, const T* host, const size_t offset = 0) { + if (access_ == BufferAccess::kReadOnly) { + throw LogicError("Buffer: writing to a read-only buffer"); + } if (GetSize() < (offset+size)*sizeof(T)) { throw LogicError("Buffer: target device buffer is too small"); } @@ -720,7 +746,7 @@ class Kernel { }) { auto status = CL_SUCCESS; *kernel_ = clCreateKernel(program(), name.c_str(), &status); - CLError::Check(status, "clCreateKernel"); + CLCudaAPIError::Check(status, "clCreateKernel"); } // Sets a kernel argument at the indicated position |