mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 23:44:01 +01:00
ircd:🆑 Add library interfacing utils; add init, infolog device banner.
ircd:🆑 Add context and device queue related init/dtor.
This commit is contained in:
parent
b47171f8f9
commit
5ad43d8817
4 changed files with 354 additions and 12 deletions
45
include/ircd/cl.h
Normal file
45
include/ircd/cl.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// The Construct
|
||||||
|
//
|
||||||
|
// Copyright (C) The Construct Developers, Authors & Contributors
|
||||||
|
// Copyright (C) 2016-2021 Jason Volk <jason@zemos.net>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#define HAVE_IRCD_CL_H
|
||||||
|
|
||||||
|
/// OpenCL Interface
|
||||||
|
namespace ircd::cl
|
||||||
|
{
|
||||||
|
IRCD_EXCEPTION(ircd::error, error)
|
||||||
|
IRCD_EXCEPTION(error, opencl_error)
|
||||||
|
|
||||||
|
struct init;
|
||||||
|
|
||||||
|
extern log::log log;
|
||||||
|
extern const info::versions version_api, version_abi;
|
||||||
|
|
||||||
|
string_view reflect_error(const int code) noexcept;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ircd::cl::init
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
~init() noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef IRCD_USE_OPENCL
|
||||||
|
inline
|
||||||
|
ircd::cl::init::init()
|
||||||
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IRCD_USE_OPENCL
|
||||||
|
inline
|
||||||
|
ircd::cl::init::~init()
|
||||||
|
noexcept
|
||||||
|
{}
|
||||||
|
#endif
|
|
@ -76,6 +76,7 @@
|
||||||
#include "globular.h"
|
#include "globular.h"
|
||||||
#include "tokens.h"
|
#include "tokens.h"
|
||||||
#include "iov.h"
|
#include "iov.h"
|
||||||
|
#include "cl.h"
|
||||||
#include "grammar.h"
|
#include "grammar.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
319
ircd/cl.cc
319
ircd/cl.cc
|
@ -8,32 +8,327 @@
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
// full license for this software is available in the LICENSE file.
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
#include <ircd/ircd.h>
|
|
||||||
#include <CL/cl.h>
|
#include <CL/cl.h>
|
||||||
|
|
||||||
|
// Util
|
||||||
namespace ircd::cl
|
namespace ircd::cl
|
||||||
{
|
{
|
||||||
extern const info::versions opencl_version_api, opencl_version_abi;
|
static bool is_error(const int &code) noexcept;
|
||||||
|
static int throw_on_error(const int &code);
|
||||||
|
template<class func, class... args> static int call(func&&, args&&...);
|
||||||
|
template<class T = string_view, class F, class id, class param> static T info(F&&, const id &, const param &, const mutable_buffer &);
|
||||||
}
|
}
|
||||||
|
|
||||||
decltype(ircd::cl::opencl_version_api)
|
// Runtime state
|
||||||
ircd::cl::opencl_version_api
|
namespace ircd::cl
|
||||||
|
{
|
||||||
|
static const size_t
|
||||||
|
PLATFORM_MAX {8},
|
||||||
|
DEVICE_MAX {8};
|
||||||
|
|
||||||
|
static uint
|
||||||
|
platforms,
|
||||||
|
devices[PLATFORM_MAX];
|
||||||
|
|
||||||
|
static cl_platform_id
|
||||||
|
platform[PLATFORM_MAX];
|
||||||
|
|
||||||
|
static cl_device_id
|
||||||
|
device[PLATFORM_MAX][DEVICE_MAX];
|
||||||
|
|
||||||
|
static cl_context
|
||||||
|
primary;
|
||||||
|
|
||||||
|
static cl_command_queue
|
||||||
|
queue[PLATFORM_MAX][DEVICE_MAX];
|
||||||
|
|
||||||
|
static void handle_notify(const char *, const void *, size_t, void *) noexcept;
|
||||||
|
}
|
||||||
|
|
||||||
|
decltype(ircd::cl::log)
|
||||||
|
ircd::cl::log
|
||||||
|
{
|
||||||
|
"cl"
|
||||||
|
};
|
||||||
|
|
||||||
|
decltype(ircd::cl::version_api)
|
||||||
|
ircd::cl::version_api
|
||||||
{
|
{
|
||||||
"OpenCL", info::versions::API, CL_TARGET_OPENCL_VERSION,
|
"OpenCL", info::versions::API, CL_TARGET_OPENCL_VERSION,
|
||||||
{
|
{
|
||||||
#if defined(CL_VERSION_MAJOR)
|
#if defined(CL_VERSION_MAJOR) && defined(CL_VERSION_MINOR) && defined(CL_VERSION_PATCH)
|
||||||
CL_VERSION_MAJOR(CL_TARGET_OPENCL_VERSION),
|
CL_VERSION_MAJOR(CL_TARGET_OPENCL_VERSION),
|
||||||
CL_VERSION_MINOR(CL_TARGET_OPENCL_VERSION),
|
CL_VERSION_MINOR(CL_TARGET_OPENCL_VERSION),
|
||||||
CL_VERSION_PATCH(CL_TARGET_OPENCL_VERSION),
|
CL_VERSION_PATCH(CL_TARGET_OPENCL_VERSION),
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
decltype(ircd::cl::opencl_version_abi)
|
decltype(ircd::cl::version_abi)
|
||||||
ircd::cl::opencl_version_abi
|
ircd::cl::version_abi
|
||||||
{
|
{
|
||||||
"OpenCL", info::versions::ABI, 0,
|
"OpenCL", info::versions::ABI, 0,
|
||||||
{
|
{
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// init
|
||||||
|
//
|
||||||
|
|
||||||
|
ircd::cl::init::init()
|
||||||
|
{
|
||||||
|
call(clGetPlatformIDs, PLATFORM_MAX, platform, &platforms);
|
||||||
|
|
||||||
|
char buf[4][128];
|
||||||
|
for(size_t i(0); i < platforms; ++i)
|
||||||
|
log::info
|
||||||
|
{
|
||||||
|
log, "OpenCL:%d [%u][*] :%s :%s :%s :%s",
|
||||||
|
CL_TARGET_OPENCL_VERSION,
|
||||||
|
i,
|
||||||
|
info(clGetPlatformInfo, platform[i], CL_PLATFORM_VERSION, buf[0]),
|
||||||
|
info(clGetPlatformInfo, platform[i], CL_PLATFORM_VENDOR, buf[1]),
|
||||||
|
info(clGetPlatformInfo, platform[i], CL_PLATFORM_NAME, buf[2]),
|
||||||
|
info(clGetPlatformInfo, platform[i], CL_PLATFORM_EXTENSIONS, buf[3]),
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t devices_total(0);
|
||||||
|
for(size_t i(0); i < platforms; ++i)
|
||||||
|
{
|
||||||
|
static const auto type
|
||||||
|
{
|
||||||
|
CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR
|
||||||
|
};
|
||||||
|
|
||||||
|
call(clGetDeviceIDs, platform[i], type, DEVICE_MAX, device[i], devices + i);
|
||||||
|
devices_total += devices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i(0); i < platforms; ++i)
|
||||||
|
for(size_t j(0); j < devices[i]; ++j)
|
||||||
|
log::info
|
||||||
|
{
|
||||||
|
log, "OpenCL:%d [%u][%u] :%s :%s :%s :%s",
|
||||||
|
CL_TARGET_OPENCL_VERSION,
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
info(clGetDeviceInfo, device[i][j], CL_DRIVER_VERSION, buf[0]),
|
||||||
|
info(clGetDeviceInfo, device[i][j], CL_DEVICE_VERSION, buf[1]),
|
||||||
|
info(clGetDeviceInfo, device[i][j], CL_DEVICE_VENDOR, buf[2]),
|
||||||
|
info(clGetDeviceInfo, device[i][j], CL_DEVICE_NAME, buf[3]),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gather all devices we'll use.
|
||||||
|
size_t _devs {0};
|
||||||
|
cl_device_id _dev[DEVICE_MAX];
|
||||||
|
for(size_t i(0); i < platforms; ++i)
|
||||||
|
for(size_t j(0); j < devices[i]; ++j)
|
||||||
|
_dev[_devs++] = device[i][j];
|
||||||
|
|
||||||
|
// Create a context from gathered devices.
|
||||||
|
cl_int err {CL_SUCCESS};
|
||||||
|
cl_context_properties ctxprop {0};
|
||||||
|
primary = clCreateContext(&ctxprop, _devs, _dev, handle_notify, nullptr, &err);
|
||||||
|
throw_on_error(err);
|
||||||
|
|
||||||
|
// Create a queue for each device.
|
||||||
|
cl_queue_properties qprop {0};
|
||||||
|
for(size_t i(0); i < platforms; ++i)
|
||||||
|
for(size_t j(0); j < devices[i]; ++j)
|
||||||
|
{
|
||||||
|
queue[i][j] = clCreateCommandQueueWithProperties(primary, device[i][j], &qprop, &err);
|
||||||
|
throw_on_error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::cl::init::~init()
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
if(primary)
|
||||||
|
log::debug
|
||||||
|
{
|
||||||
|
log, "Shutting down OpenCL...",
|
||||||
|
};
|
||||||
|
|
||||||
|
for(size_t i(0); i < PLATFORM_MAX; ++i)
|
||||||
|
for(size_t j(0); j < DEVICE_MAX; ++j)
|
||||||
|
if(queue[i][j])
|
||||||
|
{
|
||||||
|
call(clReleaseCommandQueue, queue[i][j]);
|
||||||
|
queue[i][j] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(primary)
|
||||||
|
{
|
||||||
|
call(clReleaseContext, primary);
|
||||||
|
primary = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// callback surface
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::cl::handle_notify(const char *errstr,
|
||||||
|
const void *token,
|
||||||
|
size_t cb,
|
||||||
|
void *priv)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
if(errstr)
|
||||||
|
log::error
|
||||||
|
{
|
||||||
|
log, "OpenCL t:%p cb:%zu :%s",
|
||||||
|
token,
|
||||||
|
cb,
|
||||||
|
errstr,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// util
|
||||||
|
//
|
||||||
|
|
||||||
|
template<class T,
|
||||||
|
class F,
|
||||||
|
class id,
|
||||||
|
class param>
|
||||||
|
T
|
||||||
|
ircd::cl::info(F&& func,
|
||||||
|
const id &i,
|
||||||
|
const param &p,
|
||||||
|
const mutable_buffer &out)
|
||||||
|
{
|
||||||
|
size_t len {0};
|
||||||
|
call(std::forward<F>(func), i, p, size(out), data(out), &len);
|
||||||
|
const string_view str
|
||||||
|
{
|
||||||
|
data(out), len
|
||||||
|
};
|
||||||
|
|
||||||
|
return lex_cast<T>(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class func,
|
||||||
|
class... args>
|
||||||
|
int
|
||||||
|
ircd::cl::call(func&& f,
|
||||||
|
args&&... a)
|
||||||
|
{
|
||||||
|
const int ret
|
||||||
|
{
|
||||||
|
f(std::forward<args>(a)...)
|
||||||
|
};
|
||||||
|
|
||||||
|
return throw_on_error(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ircd::cl::throw_on_error(const int &code)
|
||||||
|
{
|
||||||
|
if(unlikely(is_error(code)))
|
||||||
|
throw opencl_error
|
||||||
|
{
|
||||||
|
"(#%d) :%s",
|
||||||
|
code,
|
||||||
|
reflect_error(code),
|
||||||
|
};
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::cl::is_error(const int &code)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return code < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::string_view
|
||||||
|
ircd::cl::reflect_error(const int code)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
switch(code)
|
||||||
|
{
|
||||||
|
case CL_SUCCESS: return "SUCCESS";
|
||||||
|
case CL_DEVICE_NOT_FOUND: return "DEVICE_NOT_FOUND";
|
||||||
|
case CL_DEVICE_NOT_AVAILABLE: return "DEVICE_NOT_AVAILABLE";
|
||||||
|
case CL_COMPILER_NOT_AVAILABLE: return "COMPILER_NOT_AVAILABLE";
|
||||||
|
case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "MEM_OBJECT_ALLOCATION_FAILURE";
|
||||||
|
case CL_OUT_OF_RESOURCES: return "OUT_OF_RESOURCES";
|
||||||
|
case CL_OUT_OF_HOST_MEMORY: return "OUT_OF_HOST_MEMORY";
|
||||||
|
case CL_PROFILING_INFO_NOT_AVAILABLE: return "PROFILING_INFO_NOT_AVAILABLE";
|
||||||
|
case CL_MEM_COPY_OVERLAP: return "MEM_COPY_OVERLAP";
|
||||||
|
case CL_IMAGE_FORMAT_MISMATCH: return "IMAGE_FORMAT_MISMATCH";
|
||||||
|
case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "IMAGE_FORMAT_NOT_SUPPORTED";
|
||||||
|
case CL_BUILD_PROGRAM_FAILURE: return "BUILD_PROGRAM_FAILURE";
|
||||||
|
case CL_MAP_FAILURE: return "MAP_FAILURE";
|
||||||
|
case CL_INVALID_VALUE: return "INVALID_VALUE";
|
||||||
|
case CL_INVALID_DEVICE_TYPE: return "INVALID_DEVICE_TYPE";
|
||||||
|
case CL_INVALID_PLATFORM: return "INVALID_PLATFORM";
|
||||||
|
case CL_INVALID_DEVICE: return "INVALID_DEVICE";
|
||||||
|
case CL_INVALID_CONTEXT: return "INVALID_CONTEXT";
|
||||||
|
case CL_INVALID_QUEUE_PROPERTIES: return "INVALID_QUEUE_PROPERTIES";
|
||||||
|
case CL_INVALID_COMMAND_QUEUE: return "INVALID_COMMAND_QUEUE";
|
||||||
|
case CL_INVALID_HOST_PTR: return "INVALID_HOST_PTR";
|
||||||
|
case CL_INVALID_MEM_OBJECT: return "INVALID_MEM_OBJECT";
|
||||||
|
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "INVALID_IMAGE_FORMAT_DESCRIPTOR";
|
||||||
|
case CL_INVALID_IMAGE_SIZE: return "INVALID_IMAGE_SIZE";
|
||||||
|
case CL_INVALID_SAMPLER: return "INVALID_SAMPLER";
|
||||||
|
case CL_INVALID_BINARY: return "INVALID_BINARY";
|
||||||
|
case CL_INVALID_BUILD_OPTIONS: return "INVALID_BUILD_OPTIONS";
|
||||||
|
case CL_INVALID_PROGRAM: return "INVALID_PROGRAM";
|
||||||
|
case CL_INVALID_PROGRAM_EXECUTABLE: return "INVALID_PROGRAM_EXECUTABLE";
|
||||||
|
case CL_INVALID_KERNEL_NAME: return "INVALID_KERNEL_NAME";
|
||||||
|
case CL_INVALID_KERNEL_DEFINITION: return "INVALID_KERNEL_DEFINITION";
|
||||||
|
case CL_INVALID_KERNEL: return "INVALID_KERNEL";
|
||||||
|
case CL_INVALID_ARG_INDEX: return "INVALID_ARG_INDEX";
|
||||||
|
case CL_INVALID_ARG_VALUE: return "INVALID_ARG_VALUE";
|
||||||
|
case CL_INVALID_ARG_SIZE: return "INVALID_ARG_SIZE";
|
||||||
|
case CL_INVALID_KERNEL_ARGS: return "INVALID_KERNEL_ARGS";
|
||||||
|
case CL_INVALID_WORK_DIMENSION: return "INVALID_WORK_DIMENSION";
|
||||||
|
case CL_INVALID_WORK_GROUP_SIZE: return "INVALID_WORK_GROUP_SIZE";
|
||||||
|
case CL_INVALID_WORK_ITEM_SIZE: return "INVALID_WORK_ITEM_SIZE";
|
||||||
|
case CL_INVALID_GLOBAL_OFFSET: return "INVALID_GLOBAL_OFFSET";
|
||||||
|
case CL_INVALID_EVENT_WAIT_LIST: return "INVALID_EVENT_WAIT_LIST";
|
||||||
|
case CL_INVALID_EVENT: return "INVALID_EVENT";
|
||||||
|
case CL_INVALID_OPERATION: return "INVALID_OPERATION";
|
||||||
|
case CL_INVALID_GL_OBJECT: return "INVALID_GL_OBJECT";
|
||||||
|
case CL_INVALID_BUFFER_SIZE: return "INVALID_BUFFER_SIZE";
|
||||||
|
case CL_INVALID_MIP_LEVEL: return "INVALID_MIP_LEVEL";
|
||||||
|
case CL_INVALID_GLOBAL_WORK_SIZE: return "INVALID_GLOBAL_WORK_SIZE";
|
||||||
|
|
||||||
|
#ifdef CL_VERSION_1_1
|
||||||
|
case CL_INVALID_PROPERTY: return "INVALID_PROPERTY";
|
||||||
|
case CL_MISALIGNED_SUB_BUFFER_OFFSET: return "MISALIGNED_SUB_BUFFER_OFFSET";
|
||||||
|
case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: return "EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CL_VERSION_1_2
|
||||||
|
case CL_COMPILE_PROGRAM_FAILURE: return "COMPILE_PROGRAM_FAILURE";
|
||||||
|
case CL_LINKER_NOT_AVAILABLE: return "LINKER_NOT_AVAILABLE";
|
||||||
|
case CL_LINK_PROGRAM_FAILURE: return "LINK_PROGRAM_FAILURE";
|
||||||
|
case CL_DEVICE_PARTITION_FAILED: return "DEVICE_PARTITION_FAILED";
|
||||||
|
case CL_KERNEL_ARG_INFO_NOT_AVAILABLE: return "KERNEL_ARG_INFO_NOT_AVAILABLE";
|
||||||
|
case CL_INVALID_IMAGE_DESCRIPTOR: return "INVALID_IMAGE_DESCRIPTOR";
|
||||||
|
case CL_INVALID_COMPILER_OPTIONS: return "INVALID_COMPILER_OPTIONS";
|
||||||
|
case CL_INVALID_LINKER_OPTIONS: return "INVALID_LINKER_OPTIONS";
|
||||||
|
case CL_INVALID_DEVICE_PARTITION_COUNT: return "INVALID_DEVICE_PARTITION_COUNT";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CL_VERSION_2_0
|
||||||
|
case CL_INVALID_PIPE_SIZE: return "INVALID_PIPE_SIZE";
|
||||||
|
case CL_INVALID_DEVICE_QUEUE: return "INVALID_DEVICE_QUEUE";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CL_VERSION_2_2
|
||||||
|
case CL_INVALID_SPEC_ID: return "INVALID_SPEC_ID";
|
||||||
|
case CL_MAX_SIZE_RESTRICTION_EXCEEDED: return "MAX_SIZE_RESTRICTION_EXCEEDED";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return "???????";
|
||||||
|
}
|
||||||
|
|
|
@ -365,6 +365,7 @@ noexcept try
|
||||||
// more appropriate.
|
// more appropriate.
|
||||||
|
|
||||||
fs::init _fs_; // Local filesystem
|
fs::init _fs_; // Local filesystem
|
||||||
|
cl::init _cl_; // OpenCL
|
||||||
magic::init _magic_; // libmagic
|
magic::init _magic_; // libmagic
|
||||||
ctx::ole::init _ole_; // Thread OffLoad Engine
|
ctx::ole::init _ole_; // Thread OffLoad Engine
|
||||||
magick::init _magick_; // ImageMagick
|
magick::init _magick_; // ImageMagick
|
||||||
|
|
Loading…
Reference in a new issue