0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-13 16:33:53 +01:00

ircd:🆑 Re-attempt pre-SVM mapping w/ synchronous closure.

This commit is contained in:
Jason Volk 2021-03-17 17:15:03 -07:00
parent d69f8ffb9c
commit a21589654a
2 changed files with 190 additions and 10 deletions

View file

@ -14,9 +14,6 @@
/// OpenCL Interface
namespace ircd::cl
{
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, opencl_error)
struct init;
struct exec;
struct kern;
@ -24,6 +21,12 @@ namespace ircd::cl
struct data;
struct work;
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, opencl_error)
using read_closure = std::function<void (const_buffer)>;
using write_closure = std::function<void (mutable_buffer)>;
extern const info::versions version_api;
extern info::versions version_abi;
extern conf::item<bool> enable;
@ -143,12 +146,18 @@ struct ircd::cl::exec
static const opts opts_default;
// Read data from the device into buffer.
exec(data &, const mutable_buffer &, const opts & = opts_default);
// View data written by the device to the GTT (synchronous closure).
exec(data &, const read_closure &, const opts & = opts_default);
// Write data to the device from buffer.
// View buffer in the GTT which the device will read (synchronous closure).
exec(data &, const write_closure &, const opts & = opts_default);
// Copy data from the buffer to the GTT for use by the device.
exec(data &, const const_buffer &, const opts & = opts_default);
// Copy data written by the device to the GTT into our buffer.
exec(data &, const mutable_buffer &, const opts & = opts_default);
// Execute a kernel on a range.
exec(kern &, const kern::range &, const opts & = opts_default);
@ -166,8 +175,21 @@ struct ircd::cl::exec::opts
/// the default.
vector_view<cl::exec> deps;
/// For operations that have an optional blocking behavior;
/// otherwise ignored.
/// For operations which have a size; otherwise ignored, or serves as
/// sentinel for automatic size.
size_t size {0};
/// For operations which have an offset; otherwise ignored.
off_t offset {0};
/// For operations which plan to both read and write to the GTT, set to
/// true and execute the write_closure; otherwise ignored. Can be used
/// to de-optimize the write_closure, which is unidirectional by default.
bool duplex {false};
/// For operations that have an optional blocking behavior; otherwise
/// ignored. Note that this is a thread-level blocking mechanism and
/// does not yield the ircd::ctx; for testing/special use only.
bool blocking {false};
};

View file

@ -387,7 +387,7 @@ try
q,
cl_mem(data.handle),
opts.blocking,
0UL, //offset,
opts.offset,
ircd::size(buf),
ircd::data(buf),
deps.size(),
@ -421,13 +421,14 @@ try
make_deps(this, opts)
};
assert(!this->handle);
call
(
clEnqueueWriteBuffer,
q,
cl_mem(data.handle),
opts.blocking,
0UL, //offset,
opts.offset,
ircd::size(buf),
mutable_cast(ircd::data(buf)),
deps.size(),
@ -446,6 +447,163 @@ catch(const std::exception &e)
throw;
}
ircd::cl::exec::exec(data &data,
const read_closure &closure,
const opts &opts)
try
{
auto &q
{
queue[0][0]
};
const auto deps
{
make_deps(this, opts)
};
const auto size
{
opts.size?: data.size()
};
cl_map_flags flags {0};
flags |= CL_MAP_READ;
int err {CL_SUCCESS};
assert(!this->handle);
void *const ptr
{
clEnqueueMapBuffer
(
q,
cl_mem(data.handle),
opts.blocking,
flags,
opts.offset,
size,
deps.size(),
deps.size()? deps.data(): nullptr,
reinterpret_cast<cl_event *>(&this->handle),
&err
)
};
throw_on_error(err);
assert(this->handle);
assert(ptr);
const unwind unmap{[this, &data, &q, &ptr]
{
assert(!this->handle);
call
(
clEnqueueUnmapMemObject,
q,
cl_mem(data.handle),
ptr,
0, // deps
nullptr, // depslist
reinterpret_cast<cl_event *>(&this->handle)
);
}};
wait();
closure(const_buffer
{
reinterpret_cast<const char *>(ptr), size
});
}
catch(const std::exception &e)
{
log::error
{
log, "Exec Read Closure :%s",
e.what(),
};
throw;
}
ircd::cl::exec::exec(data &data,
const write_closure &closure,
const opts &opts)
try
{
auto &q
{
queue[0][0]
};
const auto deps
{
make_deps(this, opts)
};
const auto size
{
opts.size?: data.size()
};
cl_map_flags flags {0};
flags |= CL_MAP_WRITE;
flags |= opts.duplex? CL_MAP_READ: 0;
int err {CL_SUCCESS};
assert(!this->handle);
void *const ptr
{
clEnqueueMapBuffer
(
q,
cl_mem(data.handle),
opts.blocking,
flags,
opts.offset,
size,
deps.size(),
deps.size()? deps.data(): nullptr,
reinterpret_cast<cl_event *>(&this->handle),
&err
)
};
throw_on_error(err);
assert(this->handle);
assert(ptr);
const unwind unmap{[this, &data, &q, &ptr]
{
assert(!this->handle);
call
(
clEnqueueUnmapMemObject,
q,
cl_mem(data.handle),
ptr,
0, // deps
nullptr, // depslist
reinterpret_cast<cl_event *>(&this->handle)
);
}};
wait();
closure(mutable_buffer
{
reinterpret_cast<char *>(ptr), size
});
}
catch(const std::exception &e)
{
log::error
{
log, "Exec Write Closure :%s",
e.what(),
};
throw;
}
ircd::vector_view<cl_event>
ircd::cl::make_deps(cl::work *const &work,
const exec::opts &opts)