summaryrefslogtreecommitdiff
path: root/src/clpp11.hpp
diff options
context:
space:
mode:
authorCedric Nugteren <web@cedricnugteren.nl>2017-10-28 17:32:37 +0200
committerCedric Nugteren <web@cedricnugteren.nl>2017-10-28 17:32:37 +0200
commit12b08ae49154379f7471a40809ace6418857b387 (patch)
treeef958197db0bb8a67c9a5840f828b3f6c72bd8fc /src/clpp11.hpp
parent2949e156f5bfdd724987e67477da3e3608e4aaf9 (diff)
parentfa6e5e67f585b77d34c3031c176de9a0f7904aa9 (diff)
Merge branch 'master' into android_support
Diffstat (limited to 'src/clpp11.hpp')
-rw-r--r--src/clpp11.hpp88
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