Skip to content

Commit 12e9e85

Browse files
committed
Register new command group to execute host pipe read/write operation
Defines the flow of enqueue new host pipe operations (read/write), User provide the queue to enqueue this event, and the runtime queries the pipe address from registration using the given address and unique ID. The runtime pass the pipe name, and host address into queue submit of new command group. The enqueued command calls new opencl function, and provide the current program, queue, event wait list, pipe name, host pointer of the data destination. Spec: #5838
1 parent a8bc6ea commit 12e9e85

File tree

10 files changed

+287
-2
lines changed

10 files changed

+287
-2
lines changed

sycl/include/CL/sycl/detail/cg.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class CG {
170170
CodeplayInteropTask = 13,
171171
CodeplayHostTask = 14,
172172
AdviseUSM = 15,
173+
ReadWriteHostPipe = 16,
173174
};
174175

175176
CG(CGTYPE Type, std::vector<std::vector<char>> ArgsStorage,
@@ -522,6 +523,36 @@ class CGBarrier : public CG {
522523
MEventsWaitWithBarrier(std::move(EventsWaitWithBarrier)) {}
523524
};
524525

526+
/// "ReadWriteHostPipe" command group class.
527+
class CGReadWriteHostPipe : public CG {
528+
std::string PipeName;
529+
bool Blocking;
530+
void *HostPtr;
531+
size_t TypeSize;
532+
bool IsReadOp;
533+
534+
public:
535+
CGReadWriteHostPipe(const std::string &Name, bool Block, void *Ptr,
536+
size_t Size, bool Read,
537+
std::vector<std::vector<char>> ArgsStorage,
538+
std::vector<detail::AccessorImplPtr> AccStorage,
539+
std::vector<std::shared_ptr<const void>> SharedPtrStorage,
540+
std::vector<Requirement *> Requirements,
541+
std::vector<detail::EventImplPtr> Events,
542+
detail::code_location loc = {})
543+
: CG(ReadWriteHostPipe, std::move(ArgsStorage), std::move(AccStorage),
544+
std::move(SharedPtrStorage), std::move(Requirements),
545+
std::move(Events), std::move(loc)),
546+
PipeName(Name), Blocking(Block), HostPtr(Ptr), TypeSize(Size),
547+
IsReadOp(Read) {}
548+
549+
std::string getPipeName() { return PipeName; }
550+
void *getHostPtr() { return HostPtr; }
551+
size_t getTypeSize() { return TypeSize; }
552+
bool isBlocking() { return Blocking; }
553+
bool isReadHostPipe() { return IsReadOp; }
554+
};
555+
525556
} // namespace detail
526557
} // namespace sycl
527558
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/CL/sycl/handler.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,6 +2612,15 @@ class __SYCL_EXPORT handler {
26122612
/// \param Advice is a device-defined advice for the specified allocation.
26132613
void mem_advise(const void *Ptr, size_t Length, int Advice);
26142614

2615+
/// Read from or write to host pipes given a host address and
2616+
/// \param Name name of the host pipe to be passed into lower level runtime
2617+
/// \param Ptr host pointer of host pipe as identified by address of its const
2618+
/// expr __pipe member \param Size the size of data getting read back / to.
2619+
/// /// \param Size the size of data getting read back / to. \param Blocking
2620+
/// if read/write opeartion is blocking \param Read 1 for read, 0 for write
2621+
void read_write_host_pipe(const std::string &Name, void *Ptr, size_t Size,
2622+
bool Block, bool Read);
2623+
26152624
private:
26162625
std::shared_ptr<detail::queue_impl> MQueue;
26172626
/// The storage for the arguments passed.
@@ -2660,6 +2669,16 @@ class __SYCL_EXPORT handler {
26602669
/// The list of valid SYCL events that need to complete
26612670
/// before barrier command can be executed
26622671
std::vector<detail::EventImplPtr> MEventsWaitWithBarrier;
2672+
/// Pipe name that uniquely identifies a pipe.
2673+
std::string HostPipeName;
2674+
/// Pipe host pointer, the address of its constexpr __pipe member.
2675+
void *HostPipePtr = nullptr;
2676+
/// Host pipe read write operation is blocking.
2677+
bool HostPipeBlocking = false;
2678+
/// The size of returned type for each read.
2679+
size_t HostPipeTypeSize = 0;
2680+
/// If the pipe operation is read or write, 1 for read 0 for write.
2681+
bool HostPipeRead = true;
26632682

26642683
bool MIsHost = false;
26652684

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//==---------------- pipes.hpp - SYCL pipes ------------*- C++ -*-----------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
// ===--------------------------------------------------------------------=== //
8+
9+
#pragma once
10+
11+
#include <CL/sycl/context.hpp>
12+
#include <CL/sycl/device.hpp>
13+
#include <CL/sycl/queue.hpp>
14+
#include <sycl/ext/intel/experimental/pipe_properties.hpp>
15+
#include <sycl/ext/oneapi/properties/properties.hpp>
16+
#include <type_traits>
17+
18+
#ifdef XPTI_ENABLE_INSTRUMENTATION
19+
#include <xpti/xpti_data_types.h>
20+
#include <xpti/xpti_trace_framework.hpp>
21+
#endif
22+
23+
__SYCL_INLINE_NAMESPACE(cl) {
24+
namespace sycl {
25+
namespace ext {
26+
namespace intel {
27+
namespace experimental {
28+
29+
template <class _name, class _dataT,
30+
class _propertiesT = decltype(oneapi::experimental::properties{}),
31+
class = void>
32+
class host_pipe {
33+
static_assert(
34+
sycl::ext::oneapi::experimental::is_property_list_v<_propertiesT>,
35+
"Host pipe is available only through new property list");
36+
};
37+
38+
using default_pipe_properties =
39+
decltype(sycl::ext::oneapi::experimental::properties(min_capacity<0>));
40+
41+
template <class _name, class _dataT, class _propertiesT>
42+
class
43+
#ifdef __SYCL_DEVICE_ONLY__
44+
[[__sycl_detail__::add_ir_attributes_global_variable("sycl-host-access",
45+
"readwrite")]]
46+
#endif
47+
// TODO: change name to pipe, and merge into the existing pipe
48+
// implementation
49+
host_pipe<_name, _dataT, _propertiesT,
50+
std::enable_if_t<sycl::ext::oneapi::experimental::
51+
is_property_list_v<_propertiesT>>> {
52+
static_assert(
53+
sycl::ext::oneapi::experimental::is_property_list_v<_propertiesT>,
54+
"Host pipe is available only through new property list");
55+
56+
public:
57+
using value_type = _dataT;
58+
static constexpr int32_t min_cap =
59+
_propertiesT::template has_property<min_capacity_key>()
60+
? _propertiesT::template get_property<min_capacity_key>().value
61+
: 0;
62+
63+
// Blocking pipes
64+
static _dataT read(queue & q, memory_order order = memory_order::seq_cst);
65+
static void write(queue & q, const _dataT &data,
66+
memory_order order = memory_order::seq_cst);
67+
// Non-blocking pipes
68+
static _dataT read(queue & q, bool &success_code,
69+
memory_order order = memory_order::seq_cst);
70+
static void write(queue & q, const _dataT &data, bool &success_code,
71+
memory_order order = memory_order::seq_cst);
72+
73+
private:
74+
static constexpr int32_t m_Size = sizeof(_dataT);
75+
static constexpr int32_t m_Alignment = alignof(_dataT);
76+
77+
#ifdef __SYCL_DEVICE_ONLY__
78+
static constexpr struct ConstantPipeStorage m_Storage = {m_Size, m_Alignment,
79+
min_capacity};
80+
#endif // __SYCL_DEVICE_ONLY__
81+
};
82+
83+
} // namespace experimental
84+
} // namespace intel
85+
} // namespace ext
86+
} // namespace sycl
87+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ set(SYCL_SOURCES
142142
"detail/global_handler.cpp"
143143
"detail/helpers.cpp"
144144
"detail/handler_proxy.cpp"
145+
"detail/host_pipe.cpp"
145146
"detail/image_accessor_util.cpp"
146147
"detail/image_impl.cpp"
147148
"detail/kernel_impl.cpp"

sycl/source/detail/host_pipe.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//==-------------------- host_pipe.cpp -----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <sycl/ext/intel/experimental/host_pipes.hpp>
10+
11+
__SYCL_INLINE_NAMESPACE(cl) {
12+
namespace sycl {
13+
namespace ext {
14+
namespace intel {
15+
namespace experimental {
16+
17+
template <class _name, class _dataT, typename _propertiesT>
18+
_dataT
19+
host_pipe<_name, _dataT, _propertiesT,
20+
std::enable_if_t<sycl::ext::oneapi::experimental::is_property_list_v<
21+
_propertiesT>>>::read(queue &q, memory_order order) {
22+
const device Dev = q.get_device();
23+
bool IsReadPipeSupported =
24+
Dev.has_extension("cl_intel_program_scope_host_pipe");
25+
if (!IsReadPipeSupported) {
26+
return &_dataT();
27+
}
28+
// TODO: get pipe name from the pipe registration
29+
_dataT data;
30+
const std::string pipe_name = "pipename";
31+
size_t size = 4;
32+
event e = q.submit([=](handler &CGH) {
33+
CGH.read_write_host_pipe(pipe_name, (void *)(&data), (size_t)size, false,
34+
true /* read */);
35+
});
36+
e.wait();
37+
return data;
38+
}
39+
40+
template <class _name, class _dataT, typename _propertiesT>
41+
void host_pipe<
42+
_name, _dataT, _propertiesT,
43+
std::enable_if_t<sycl::ext::oneapi::experimental::is_property_list_v<
44+
_propertiesT>>>::write(queue &q, const _dataT &data,
45+
memory_order order) {
46+
const device Dev = q.get_device();
47+
bool IsReadPipeSupported =
48+
Dev.has_extension("cl_intel_program_scope_host_pipe");
49+
if (!IsReadPipeSupported) {
50+
return;
51+
}
52+
// TODO: get pipe name from the pipe registration
53+
const std::string pipe_name = "pipename";
54+
const void *data_ptr = &data;
55+
size_t size = 4;
56+
event e = q.submit([=](handler &CGH) {
57+
CGH.read_write_host_pipe(pipe_name, (void *)data_ptr, (size_t)size, false,
58+
false /* write */);
59+
});
60+
e.wait();
61+
}
62+
63+
// TODO: implement non blocking version
64+
65+
} // namespace experimental
66+
} // namespace intel
67+
} // namespace ext
68+
} // namespace sycl
69+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/detail/scheduler/commands.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,43 @@ cl_int enqueueImpKernel(
21922192
return PI_SUCCESS;
21932193
}
21942194

2195+
cl_uint enqueueReadWriteHostPipe(const QueueImplPtr &Queue,
2196+
const std::string &PipeName, bool blocking,
2197+
void *ptr, size_t size,
2198+
std::vector<RT::PiEvent> &RawEvents,
2199+
RT::PiEvent *OutEvent, bool read) {
2200+
// TODO: Few options of getting the kernel name / program object:
2201+
// 1. Encode this in the pipe registration
2202+
// 2. Initialize the pipe registration from first kernel launch, but then this
2203+
// will violate the spec
2204+
detail::OSModuleHandle M =
2205+
detail::OSUtil::getOSModuleHandle("HostPipeReadWriteKernelName");
2206+
RT::PiProgram Program =
2207+
sycl::detail::ProgramManager::getInstance().getBuiltPIProgram(
2208+
M, Queue->getContextImplPtr(), Queue->getDeviceImplPtr(),
2209+
"HostPipeReadWriteKernelName");
2210+
2211+
// Get plugin for calling opencl functions
2212+
const detail::plugin &Plugin = Queue->getPlugin();
2213+
2214+
pi_queue pi_q = Queue->getHandleRef();
2215+
pi_result Error;
2216+
if (read) {
2217+
Error =
2218+
Plugin.call_nocheck<sycl::detail::PiApiKind::piextEnqueueReadHostPipe>(
2219+
pi_q, Program, PipeName.c_str(), blocking, ptr, size,
2220+
RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0],
2221+
OutEvent);
2222+
} else {
2223+
Error =
2224+
Plugin.call_nocheck<sycl::detail::PiApiKind::piextEnqueueWriteHostPipe>(
2225+
pi_q, Program, PipeName.c_str(), blocking, ptr, size,
2226+
RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0],
2227+
OutEvent);
2228+
}
2229+
return Error;
2230+
}
2231+
21952232
cl_int ExecCGCommand::enqueueImp() {
21962233
if (getCG().getType() != CG::CGTYPE::CodeplayHostTask)
21972234
waitForPreparedHostEvents();
@@ -2554,6 +2591,22 @@ cl_int ExecCGCommand::enqueueImp() {
25542591

25552592
return PI_SUCCESS;
25562593
}
2594+
case CG::CGTYPE::ReadWriteHostPipe: {
2595+
CGReadWriteHostPipe *ExecReadWriteHostPipe =
2596+
(CGReadWriteHostPipe *)MCommandGroup.get();
2597+
std::string pipeName = ExecReadWriteHostPipe->getPipeName();
2598+
void *hostPtr = ExecReadWriteHostPipe->getHostPtr();
2599+
size_t typeSize = ExecReadWriteHostPipe->getTypeSize();
2600+
bool blocking = ExecReadWriteHostPipe->isBlocking();
2601+
bool read = ExecReadWriteHostPipe->isReadHostPipe();
2602+
2603+
if (!Event) {
2604+
Event = &MEvent->getHandleRef();
2605+
}
2606+
2607+
return enqueueReadWriteHostPipe(MQueue, pipeName, blocking, hostPtr,
2608+
typeSize, RawEvents, Event, read);
2609+
}
25572610
case CG::CGTYPE::None:
25582611
throw runtime_error("CG type not implemented.", PI_INVALID_OPERATION);
25592612
}

sycl/source/detail/scheduler/commands.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,12 @@ class MemCpyCommandHost : public Command {
526526
void **MDstPtr = nullptr;
527527
};
528528

529+
cl_uint enqueueReadWriteHostPipe(const QueueImplPtr &Queue,
530+
const std::string &PipeName, bool blocking,
531+
void *ptr, size_t size,
532+
std::vector<RT::PiEvent> &RawEvents,
533+
RT::PiEvent *OutEvent, bool read);
534+
529535
cl_int enqueueImpKernel(
530536
const QueueImplPtr &Queue, NDRDescT &NDRDesc, std::vector<ArgDesc> &Args,
531537
const std::shared_ptr<detail::kernel_bundle_impl> &KernelBundleImplPtr,

sycl/source/handler.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,13 @@ event handler::finalize() {
381381
std::move(MAccStorage), std::move(MSharedPtrStorage),
382382
std::move(MRequirements), std::move(MEvents), MCGType, MCodeLoc));
383383
break;
384+
case detail::CG::ReadWriteHostPipe:
385+
CommandGroup.reset(new detail::CGReadWriteHostPipe(
386+
HostPipeName, HostPipeBlocking, HostPipePtr, HostPipeTypeSize,
387+
HostPipeRead, std::move(MArgsStorage), std::move(MAccStorage),
388+
std::move(MSharedPtrStorage), std::move(MRequirements),
389+
std::move(MEvents), MCodeLoc));
390+
break;
384391
case detail::CG::None:
385392
if (detail::pi::trace(detail::pi::TraceLevel::PI_TRACE_ALL)) {
386393
std::cout << "WARNING: An empty command group is submitted." << std::endl;
@@ -814,5 +821,16 @@ void handler::depends_on(const std::vector<event> &Events) {
814821
}
815822
}
816823

824+
void handler::read_write_host_pipe(const std::string &Name, void *Ptr,
825+
size_t Size, bool Block, bool Read) {
826+
throwIfActionIsCreated();
827+
HostPipeName = Name;
828+
HostPipePtr = Ptr;
829+
HostPipeTypeSize = Size;
830+
HostPipeBlocking = Block;
831+
HostPipeRead = Read;
832+
setType(detail::CG::ReadWriteHostPipe);
833+
}
834+
817835
} // namespace sycl
818836
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/test/abi/sycl_symbols_linux.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4006,6 +4006,7 @@ _ZN2cl4sycl7handler18ext_oneapi_barrierERKSt6vectorINS0_5eventESaIS3_EE
40064006
_ZN2cl4sycl7handler18extractArgsAndReqsEv
40074007
_ZN2cl4sycl7handler20DisableRangeRoundingEv
40084008
_ZN2cl4sycl7handler20associateWithHandlerEPNS0_6detail16AccessorBaseHostENS0_6access6targetE
4009+
_ZN2cl4sycl7handler20read_write_host_pipeERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPvmbb
40094010
_ZN2cl4sycl7handler20setStateSpecConstSetEv
40104011
_ZN2cl4sycl7handler22setHandlerKernelBundleERKSt10shared_ptrINS0_6detail18kernel_bundle_implEE
40114012
_ZN2cl4sycl7handler22verifyUsedKernelBundleERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

sycl/test/abi/symbol_size_alignment.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ int main() {
5858
check<event, 16, 8>();
5959
check<gpu_selector, 8, 8>();
6060
#ifdef _MSC_VER
61-
check<handler, 552, 8>();
61+
check<handler, 608, 8>();
6262
check<detail::buffer_impl, 216, 8>();
6363
check<detail::image_impl<1>, 272, 8>();
6464
#else
65-
check<handler, 560, 8>();
65+
check<handler, 616, 8>();
6666
check<detail::buffer_impl, 184, 8>();
6767
check<detail::image_impl<1>, 240, 8>();
6868
#endif

0 commit comments

Comments
 (0)