From 509db4e5e4c5bb2c87123133fa2e46a36eb27655 Mon Sep 17 00:00:00 2001 From: Joan Bruguera Date: Thu, 7 May 2020 19:19:47 +0200 Subject: [PATCH] Original dopencl-0.4.0_r1819-asio code for archival purposes. --- CMakeLists.txt | 86 + COPYING | 674 +++++++ COPYING.academic | 37 + INSTALL_Linux.txt | 116 ++ README_Linux.txt | 219 ++ daemon/CMakeLists.txt | 50 + daemon/src/CommandQueue.cpp | 965 +++++++++ daemon/src/CommandQueue.h | 223 +++ daemon/src/Context.cpp | 134 ++ daemon/src/Context.h | 116 ++ daemon/src/Device.cpp | 96 + daemon/src/Device.h | 92 + daemon/src/Event.cpp | 458 +++++ daemon/src/Event.h | 389 ++++ daemon/src/Kernel.cpp | 188 ++ daemon/src/Kernel.h | 130 ++ daemon/src/Memory.cpp | 294 +++ daemon/src/Memory.h | 178 ++ daemon/src/Program.cpp | 217 ++ daemon/src/Program.h | 115 ++ daemon/src/Session.cpp | 247 +++ daemon/src/Session.h | 164 ++ daemon/src/command/Command.h | 91 + daemon/src/command/CopyDataCommand.h | 152 ++ daemon/src/command/SetCompleteCommand.cpp | 106 + daemon/src/command/SetCompleteCommand.h | 81 + daemon/src/dOpenCLd.cpp | 340 ++++ daemon/src/dOpenCLd.h | 151 ++ daemon/src/main.cpp | 280 +++ dclasio/CMakeLists.txt | 80 + dclasio/doc/Doxyfile.in | 1781 +++++++++++++++++ dclasio/include/CL/README.txt | 19 + dclasio/include/CL/cl_wwu_collective.h | 255 +++ dclasio/include/CL/cl_wwu_collective.txt | 140 ++ dclasio/include/CL/cl_wwu_dcl.h | 342 ++++ dclasio/include/CL/cl_wwu_dcl.txt | 140 ++ dclasio/include/dcl/Binary.h | 173 ++ dclasio/include/dcl/BlockingQueue.h | 146 ++ dclasio/include/dcl/ByteBuffer.h | 324 +++ dclasio/include/dcl/CLError.h | 92 + dclasio/include/dcl/CLObjectRegistry.h | 132 ++ dclasio/include/dcl/CommandListener.h | 76 + dclasio/include/dcl/CommandQueue.h | 196 ++ dclasio/include/dcl/CommandQueueListener.h | 66 + dclasio/include/dcl/CommunicationManager.h | 164 ++ dclasio/include/dcl/ComputeNode.h | 174 ++ dclasio/include/dcl/ConnectionListener.h | 97 + dclasio/include/dcl/Context.h | 91 + dclasio/include/dcl/ContextListener.h | 72 + dclasio/include/dcl/DCLException.h | 141 ++ dclasio/include/dcl/DCLTypes.h | 62 + dclasio/include/dcl/Daemon.h | 93 + dclasio/include/dcl/DataTransfer.h | 97 + dclasio/include/dcl/Device.h | 81 + dclasio/include/dcl/Event.h | 78 + dclasio/include/dcl/Host.h | 66 + dclasio/include/dcl/Kernel.h | 87 + dclasio/include/dcl/Memory.h | 77 + dclasio/include/dcl/Process.h | 111 + dclasio/include/dcl/Program.h | 87 + dclasio/include/dcl/ProgramBuildListener.h | 83 + dclasio/include/dcl/Remote.h | 85 + dclasio/include/dcl/Session.h | 215 ++ dclasio/include/dcl/SynchronizationListener.h | 92 + dclasio/include/dcl/dcl.dox | 11 + dclasio/include/dcl/util/Clock.h | 100 + dclasio/include/dcl/util/Logger.h | 128 ++ dclasio/include/dcl/util/README.txt | 1 + .../include/dclasio/message/BuildProgram.h | 100 + .../include/dclasio/message/CommandMessage.h | 106 + .../include/dclasio/message/CreateBuffer.h | 105 + .../dclasio/message/CreateCommandQueue.h | 105 + .../include/dclasio/message/CreateContext.h | 121 ++ dclasio/include/dclasio/message/CreateEvent.h | 101 + .../include/dclasio/message/CreateKernel.h | 96 + .../dclasio/message/CreateKernelsInProgram.h | 94 + .../dclasio/message/CreateProgramWithBinary.h | 100 + .../dclasio/message/CreateProgramWithSource.h | 97 + .../dclasio/message/DeleteCommandQueue.h | 89 + .../include/dclasio/message/DeleteContext.h | 89 + dclasio/include/dclasio/message/DeleteEvent.h | 93 + .../include/dclasio/message/DeleteKernel.h | 90 + .../include/dclasio/message/DeleteMemory.h | 89 + .../include/dclasio/message/DeleteProgram.h | 89 + .../include/dclasio/message/EnqueueBarrier.h | 98 + .../dclasio/message/EnqueueBroadcastBuffer.h | 117 ++ .../dclasio/message/EnqueueCopyBuffer.h | 118 ++ .../dclasio/message/EnqueueMapBuffer.h | 122 ++ .../include/dclasio/message/EnqueueMarker.h | 99 + .../dclasio/message/EnqueueNDRangeKernel.h | 115 ++ .../dclasio/message/EnqueueReadBuffer.h | 112 ++ .../dclasio/message/EnqueueReduceBuffer.h | 122 ++ .../dclasio/message/EnqueueUnmapBuffer.h | 118 ++ .../dclasio/message/EnqueueWaitForEvents.h | 94 + .../dclasio/message/EnqueueWriteBuffer.h | 112 ++ .../include/dclasio/message/ErrorResponse.h | 97 + .../message/EventProfilingInfosResponse.h | 104 + .../message/EventSynchronizationMessage.h | 95 + .../include/dclasio/message/FinishRequest.h | 88 + .../include/dclasio/message/FlushRequest.h | 87 + .../dclasio/message/GetEventProfilingInfos.h | 92 + .../include/dclasio/message/GetKernelInfo.h | 132 ++ .../dclasio/message/GetProgramBuildLog.h | 108 + .../include/dclasio/message/InfoResponse.h | 100 + dclasio/include/dclasio/message/Message.h | 107 + .../include/dclasio/message/ReleaseRequest.h | 105 + dclasio/include/dclasio/message/Request.h | 135 ++ dclasio/include/dclasio/message/Response.h | 115 ++ .../include/dclasio/message/SetKernelArg.h | 188 ++ dclasio/include/dclasio/message/message.dox | 13 + dclasio/src/dcl/ByteBuffer.cpp | 179 ++ dclasio/src/dcl/CLError.cpp | 78 + dclasio/src/dcl/CLObjectRegistry.cpp | 95 + dclasio/src/dcl/DCLException.cpp | 105 + dclasio/src/dcl/Remote.cpp | 69 + dclasio/src/dcl/util/Clock.cpp | 85 + dclasio/src/dcl/util/Logger.cpp | 178 ++ dclasio/src/dclasio/CommunicationManager.cpp | 132 ++ .../src/dclasio/CommunicationManagerImpl.cpp | 323 +++ .../src/dclasio/CommunicationManagerImpl.h | 219 ++ dclasio/src/dclasio/ComputeNode.cpp | 101 + .../ComputeNodeCommunicationManagerImpl.cpp | 364 ++++ .../ComputeNodeCommunicationManagerImpl.h | 162 ++ dclasio/src/dclasio/ComputeNodeImpl.cpp | 399 ++++ dclasio/src/dclasio/ComputeNodeImpl.h | 318 +++ dclasio/src/dclasio/ContextListenerImpl.cpp | 82 + dclasio/src/dclasio/ContextListenerImpl.h | 77 + dclasio/src/dclasio/DCLAsioTypes.h | 58 + dclasio/src/dclasio/DeviceImpl.cpp | 94 + dclasio/src/dclasio/DeviceImpl.h | 92 + .../dclasio/HostCommunicationManagerImpl.cpp | 166 ++ .../dclasio/HostCommunicationManagerImpl.h | 115 ++ dclasio/src/dclasio/HostImpl.cpp | 79 + dclasio/src/dclasio/HostImpl.h | 101 + dclasio/src/dclasio/ProcessImpl.cpp | 201 ++ dclasio/src/dclasio/ProcessImpl.h | 246 +++ .../src/dclasio/ProgramBuildListenerImpl.cpp | 98 + .../src/dclasio/ProgramBuildListenerImpl.h | 83 + dclasio/src/dclasio/SmartCLObjectRegistry.cpp | 69 + dclasio/src/dclasio/SmartCLObjectRegistry.h | 206 ++ dclasio/src/dclasio/comm/CLEventProcessor.cpp | 298 +++ dclasio/src/dclasio/comm/CLEventProcessor.h | 207 ++ .../src/dclasio/comm/CLRequestProcessor.cpp | 1387 +++++++++++++ dclasio/src/dclasio/comm/CLRequestProcessor.h | 126 ++ .../src/dclasio/comm/CLResponseProcessor.cpp | 130 ++ .../src/dclasio/comm/CLResponseProcessor.h | 85 + dclasio/src/dclasio/comm/ConnectionListener.h | 89 + dclasio/src/dclasio/comm/DataDispatcher.cpp | 243 +++ dclasio/src/dclasio/comm/DataDispatcher.h | 174 ++ dclasio/src/dclasio/comm/DataStream.cpp | 245 +++ dclasio/src/dclasio/comm/DataStream.h | 179 ++ dclasio/src/dclasio/comm/DataTransferImpl.h | 247 +++ .../src/dclasio/comm/MessageDispatcher.cpp | 278 +++ dclasio/src/dclasio/comm/MessageDispatcher.h | 177 ++ dclasio/src/dclasio/comm/MessageListener.h | 74 + dclasio/src/dclasio/comm/MessageQueue.cpp | 234 +++ dclasio/src/dclasio/comm/MessageQueue.h | 236 +++ dclasio/src/dclasio/comm/ResponseBuffer.cpp | 162 ++ dclasio/src/dclasio/comm/ResponseBuffer.h | 135 ++ dclasio/src/dclasio/message/BuildProgram.cpp | 91 + .../src/dclasio/message/CommandMessage.cpp | 87 + .../src/dclasio/message/ContextErrorMessage.h | 105 + dclasio/src/dclasio/message/CreateBuffer.cpp | 93 + .../dclasio/message/CreateCommandQueue.cpp | 98 + dclasio/src/dclasio/message/CreateContext.cpp | 114 ++ dclasio/src/dclasio/message/CreateEvent.cpp | 84 + dclasio/src/dclasio/message/CreateKernel.cpp | 85 + .../message/CreateKernelsInProgram.cpp | 80 + .../message/CreateProgramWithSource.cpp | 86 + .../dclasio/message/DeleteCommandQueue.cpp | 73 + dclasio/src/dclasio/message/DeleteContext.cpp | 73 + dclasio/src/dclasio/message/DeleteEvent.cpp | 73 + dclasio/src/dclasio/message/DeleteKernel.cpp | 73 + dclasio/src/dclasio/message/DeleteMemory.cpp | 73 + dclasio/src/dclasio/message/DeleteProgram.cpp | 71 + .../src/dclasio/message/DeviceIDsResponse.h | 100 + .../dclasio/message/DeviceInfosResponse.cpp | 101 + .../src/dclasio/message/DeviceInfosResponse.h | 116 ++ .../src/dclasio/message/EnqueueBarrier.cpp | 91 + .../message/EnqueueBroadcastBuffer.cpp | 124 ++ .../src/dclasio/message/EnqueueCopyBuffer.cpp | 124 ++ .../src/dclasio/message/EnqueueMapBuffer.cpp | 127 ++ dclasio/src/dclasio/message/EnqueueMarker.cpp | 91 + .../dclasio/message/EnqueueNDRangeKernel.cpp | 117 ++ .../src/dclasio/message/EnqueueReadBuffer.cpp | 116 ++ .../dclasio/message/EnqueueReduceBuffer.cpp | 127 ++ .../dclasio/message/EnqueueUnmapBuffer.cpp | 123 ++ .../dclasio/message/EnqueueWaitForEvents.cpp | 77 + .../dclasio/message/EnqueueWriteBuffer.cpp | 116 ++ dclasio/src/dclasio/message/ErrorResponse.cpp | 81 + .../message/EventProfilingInfosResponse.cpp | 82 + .../message/EventSynchronizationMessage.cpp | 76 + dclasio/src/dclasio/message/FinishRequest.cpp | 72 + dclasio/src/dclasio/message/FlushRequest.cpp | 72 + dclasio/src/dclasio/message/GetDeviceIDs.h | 96 + dclasio/src/dclasio/message/GetDeviceInfo.h | 103 + .../message/GetEventProfilingInfos.cpp | 70 + dclasio/src/dclasio/message/GetKernelInfo.cpp | 126 ++ dclasio/src/dclasio/message/InfoResponse.cpp | 77 + dclasio/src/dclasio/message/Message.cpp | 163 ++ .../src/dclasio/message/ProgramBuildMessage.h | 115 ++ .../src/dclasio/message/ReleaseRequest.cpp | 84 + dclasio/src/dclasio/message/Request.cpp | 63 + dclasio/src/dclasio/message/Response.cpp | 98 + dclasio/src/dclasio/message/SetKernelArg.cpp | 163 ++ icdpp/CMakeLists.txt | 64 + icdpp/src/CommandQueue.cpp | 1007 ++++++++++ icdpp/src/CommandQueue.h | 278 +++ icdpp/src/ComputeNode.cpp | 187 ++ icdpp/src/ComputeNode.h | 143 ++ icdpp/src/Context.cpp | 363 ++++ icdpp/src/Context.h | 202 ++ icdpp/src/Device.cpp | 163 ++ icdpp/src/Device.h | 90 + icdpp/src/Event.cpp | 307 +++ icdpp/src/Event.h | 207 ++ icdpp/src/Kernel.cpp | 408 ++++ icdpp/src/Kernel.h | 165 ++ icdpp/src/Memory.cpp | 416 ++++ icdpp/src/Memory.h | 230 +++ icdpp/src/Platform.cpp | 326 +++ icdpp/src/Platform.h | 180 ++ icdpp/src/Program.cpp | 542 +++++ icdpp/src/Program.h | 191 ++ icdpp/src/Retainable.cpp | 74 + icdpp/src/Retainable.h | 86 + icdpp/src/cl.cpp | 1556 ++++++++++++++ icdpp/src/cl_khr_icd.cpp | 262 +++ icdpp/src/cl_khr_icd.h | 852 ++++++++ icdpp/src/cl_wwu_collective.cpp | 172 ++ icdpp/src/cl_wwu_dcl.cpp | 278 +++ icdpp/src/dclicd/Buffer.cpp | 216 ++ icdpp/src/dclicd/Buffer.h | 119 ++ icdpp/src/dclicd/Error.cpp | 95 + icdpp/src/dclicd/Error.h | 101 + icdpp/src/dclicd/Event.cpp | 420 ++++ icdpp/src/dclicd/Event.h | 228 +++ icdpp/src/dclicd/command/Command.cpp | 198 ++ icdpp/src/dclicd/command/Command.h | 147 ++ icdpp/src/dclicd/command/MappingCommand.cpp | 158 ++ icdpp/src/dclicd/command/MappingCommand.h | 112 ++ icdpp/src/dclicd/command/ReadWriteCommand.cpp | 101 + icdpp/src/dclicd/command/ReadWriteCommand.h | 97 + icdpp/src/dclicd/command/Readme.txt | 16 + icdpp/src/dclicd/detail/ContextProperties.cpp | 226 +++ icdpp/src/dclicd/detail/ContextProperties.h | 113 ++ .../src/dclicd/detail/EventProfilingInfo.cpp | 100 + icdpp/src/dclicd/detail/EventProfilingInfo.h | 108 + icdpp/src/dclicd/detail/KernelArgument.cpp | 77 + icdpp/src/dclicd/detail/KernelArgument.h | 81 + icdpp/src/dclicd/detail/KernelInfo.h | 101 + icdpp/src/dclicd/detail/MappedMemory.h | 112 ++ icdpp/src/dclicd/detail/ProgramBuild.cpp | 255 +++ icdpp/src/dclicd/detail/ProgramBuild.h | 153 ++ icdpp/src/dclicd/detail/ProgramBuildInfo.cpp | 54 + icdpp/src/dclicd/detail/ProgramBuildInfo.h | 75 + icdpp/src/dclicd/detail/Retainable.h | 119 ++ icdpp/src/dclicd/utility.cpp | 110 + icdpp/src/dclicd/utility.h | 142 ++ test/CMakeLists.txt | 54 + .../boost/test/parameterized_test_ex.hpp | 45 + test/src/Buffer.cpp | 134 ++ test/src/CommandQueue.cpp | 199 ++ test/src/Context.cpp | 147 ++ test/src/Device.cpp | 133 ++ test/src/Event.cpp | 240 +++ test/src/Mapping.cpp | 166 ++ test/src/Memory.cpp | 49 + test/src/MemoryConsistency.cpp | 223 +++ test/src/Platform.cpp | 122 ++ test/src/Program.cpp | 187 ++ test/src/utility.cpp | 197 ++ test/src/utility.h | 153 ++ 273 files changed, 45363 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 COPYING.academic create mode 100644 INSTALL_Linux.txt create mode 100644 README_Linux.txt create mode 100644 daemon/CMakeLists.txt create mode 100644 daemon/src/CommandQueue.cpp create mode 100644 daemon/src/CommandQueue.h create mode 100644 daemon/src/Context.cpp create mode 100644 daemon/src/Context.h create mode 100644 daemon/src/Device.cpp create mode 100644 daemon/src/Device.h create mode 100644 daemon/src/Event.cpp create mode 100644 daemon/src/Event.h create mode 100644 daemon/src/Kernel.cpp create mode 100644 daemon/src/Kernel.h create mode 100644 daemon/src/Memory.cpp create mode 100644 daemon/src/Memory.h create mode 100644 daemon/src/Program.cpp create mode 100644 daemon/src/Program.h create mode 100644 daemon/src/Session.cpp create mode 100644 daemon/src/Session.h create mode 100644 daemon/src/command/Command.h create mode 100644 daemon/src/command/CopyDataCommand.h create mode 100644 daemon/src/command/SetCompleteCommand.cpp create mode 100644 daemon/src/command/SetCompleteCommand.h create mode 100644 daemon/src/dOpenCLd.cpp create mode 100644 daemon/src/dOpenCLd.h create mode 100644 daemon/src/main.cpp create mode 100644 dclasio/CMakeLists.txt create mode 100644 dclasio/doc/Doxyfile.in create mode 100644 dclasio/include/CL/README.txt create mode 100644 dclasio/include/CL/cl_wwu_collective.h create mode 100644 dclasio/include/CL/cl_wwu_collective.txt create mode 100644 dclasio/include/CL/cl_wwu_dcl.h create mode 100644 dclasio/include/CL/cl_wwu_dcl.txt create mode 100644 dclasio/include/dcl/Binary.h create mode 100644 dclasio/include/dcl/BlockingQueue.h create mode 100644 dclasio/include/dcl/ByteBuffer.h create mode 100644 dclasio/include/dcl/CLError.h create mode 100644 dclasio/include/dcl/CLObjectRegistry.h create mode 100644 dclasio/include/dcl/CommandListener.h create mode 100644 dclasio/include/dcl/CommandQueue.h create mode 100644 dclasio/include/dcl/CommandQueueListener.h create mode 100644 dclasio/include/dcl/CommunicationManager.h create mode 100644 dclasio/include/dcl/ComputeNode.h create mode 100644 dclasio/include/dcl/ConnectionListener.h create mode 100644 dclasio/include/dcl/Context.h create mode 100644 dclasio/include/dcl/ContextListener.h create mode 100644 dclasio/include/dcl/DCLException.h create mode 100644 dclasio/include/dcl/DCLTypes.h create mode 100644 dclasio/include/dcl/Daemon.h create mode 100644 dclasio/include/dcl/DataTransfer.h create mode 100644 dclasio/include/dcl/Device.h create mode 100644 dclasio/include/dcl/Event.h create mode 100644 dclasio/include/dcl/Host.h create mode 100644 dclasio/include/dcl/Kernel.h create mode 100644 dclasio/include/dcl/Memory.h create mode 100644 dclasio/include/dcl/Process.h create mode 100644 dclasio/include/dcl/Program.h create mode 100644 dclasio/include/dcl/ProgramBuildListener.h create mode 100644 dclasio/include/dcl/Remote.h create mode 100644 dclasio/include/dcl/Session.h create mode 100644 dclasio/include/dcl/SynchronizationListener.h create mode 100644 dclasio/include/dcl/dcl.dox create mode 100644 dclasio/include/dcl/util/Clock.h create mode 100644 dclasio/include/dcl/util/Logger.h create mode 100644 dclasio/include/dcl/util/README.txt create mode 100644 dclasio/include/dclasio/message/BuildProgram.h create mode 100644 dclasio/include/dclasio/message/CommandMessage.h create mode 100644 dclasio/include/dclasio/message/CreateBuffer.h create mode 100644 dclasio/include/dclasio/message/CreateCommandQueue.h create mode 100644 dclasio/include/dclasio/message/CreateContext.h create mode 100644 dclasio/include/dclasio/message/CreateEvent.h create mode 100644 dclasio/include/dclasio/message/CreateKernel.h create mode 100644 dclasio/include/dclasio/message/CreateKernelsInProgram.h create mode 100644 dclasio/include/dclasio/message/CreateProgramWithBinary.h create mode 100644 dclasio/include/dclasio/message/CreateProgramWithSource.h create mode 100644 dclasio/include/dclasio/message/DeleteCommandQueue.h create mode 100644 dclasio/include/dclasio/message/DeleteContext.h create mode 100644 dclasio/include/dclasio/message/DeleteEvent.h create mode 100644 dclasio/include/dclasio/message/DeleteKernel.h create mode 100644 dclasio/include/dclasio/message/DeleteMemory.h create mode 100644 dclasio/include/dclasio/message/DeleteProgram.h create mode 100644 dclasio/include/dclasio/message/EnqueueBarrier.h create mode 100644 dclasio/include/dclasio/message/EnqueueBroadcastBuffer.h create mode 100644 dclasio/include/dclasio/message/EnqueueCopyBuffer.h create mode 100644 dclasio/include/dclasio/message/EnqueueMapBuffer.h create mode 100644 dclasio/include/dclasio/message/EnqueueMarker.h create mode 100644 dclasio/include/dclasio/message/EnqueueNDRangeKernel.h create mode 100644 dclasio/include/dclasio/message/EnqueueReadBuffer.h create mode 100644 dclasio/include/dclasio/message/EnqueueReduceBuffer.h create mode 100644 dclasio/include/dclasio/message/EnqueueUnmapBuffer.h create mode 100644 dclasio/include/dclasio/message/EnqueueWaitForEvents.h create mode 100644 dclasio/include/dclasio/message/EnqueueWriteBuffer.h create mode 100644 dclasio/include/dclasio/message/ErrorResponse.h create mode 100644 dclasio/include/dclasio/message/EventProfilingInfosResponse.h create mode 100644 dclasio/include/dclasio/message/EventSynchronizationMessage.h create mode 100644 dclasio/include/dclasio/message/FinishRequest.h create mode 100644 dclasio/include/dclasio/message/FlushRequest.h create mode 100644 dclasio/include/dclasio/message/GetEventProfilingInfos.h create mode 100644 dclasio/include/dclasio/message/GetKernelInfo.h create mode 100644 dclasio/include/dclasio/message/GetProgramBuildLog.h create mode 100644 dclasio/include/dclasio/message/InfoResponse.h create mode 100644 dclasio/include/dclasio/message/Message.h create mode 100644 dclasio/include/dclasio/message/ReleaseRequest.h create mode 100644 dclasio/include/dclasio/message/Request.h create mode 100644 dclasio/include/dclasio/message/Response.h create mode 100644 dclasio/include/dclasio/message/SetKernelArg.h create mode 100644 dclasio/include/dclasio/message/message.dox create mode 100644 dclasio/src/dcl/ByteBuffer.cpp create mode 100644 dclasio/src/dcl/CLError.cpp create mode 100644 dclasio/src/dcl/CLObjectRegistry.cpp create mode 100644 dclasio/src/dcl/DCLException.cpp create mode 100644 dclasio/src/dcl/Remote.cpp create mode 100644 dclasio/src/dcl/util/Clock.cpp create mode 100644 dclasio/src/dcl/util/Logger.cpp create mode 100644 dclasio/src/dclasio/CommunicationManager.cpp create mode 100644 dclasio/src/dclasio/CommunicationManagerImpl.cpp create mode 100644 dclasio/src/dclasio/CommunicationManagerImpl.h create mode 100644 dclasio/src/dclasio/ComputeNode.cpp create mode 100644 dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.cpp create mode 100644 dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.h create mode 100644 dclasio/src/dclasio/ComputeNodeImpl.cpp create mode 100644 dclasio/src/dclasio/ComputeNodeImpl.h create mode 100644 dclasio/src/dclasio/ContextListenerImpl.cpp create mode 100644 dclasio/src/dclasio/ContextListenerImpl.h create mode 100644 dclasio/src/dclasio/DCLAsioTypes.h create mode 100644 dclasio/src/dclasio/DeviceImpl.cpp create mode 100644 dclasio/src/dclasio/DeviceImpl.h create mode 100644 dclasio/src/dclasio/HostCommunicationManagerImpl.cpp create mode 100644 dclasio/src/dclasio/HostCommunicationManagerImpl.h create mode 100644 dclasio/src/dclasio/HostImpl.cpp create mode 100644 dclasio/src/dclasio/HostImpl.h create mode 100644 dclasio/src/dclasio/ProcessImpl.cpp create mode 100644 dclasio/src/dclasio/ProcessImpl.h create mode 100644 dclasio/src/dclasio/ProgramBuildListenerImpl.cpp create mode 100644 dclasio/src/dclasio/ProgramBuildListenerImpl.h create mode 100644 dclasio/src/dclasio/SmartCLObjectRegistry.cpp create mode 100644 dclasio/src/dclasio/SmartCLObjectRegistry.h create mode 100644 dclasio/src/dclasio/comm/CLEventProcessor.cpp create mode 100644 dclasio/src/dclasio/comm/CLEventProcessor.h create mode 100644 dclasio/src/dclasio/comm/CLRequestProcessor.cpp create mode 100644 dclasio/src/dclasio/comm/CLRequestProcessor.h create mode 100644 dclasio/src/dclasio/comm/CLResponseProcessor.cpp create mode 100644 dclasio/src/dclasio/comm/CLResponseProcessor.h create mode 100644 dclasio/src/dclasio/comm/ConnectionListener.h create mode 100644 dclasio/src/dclasio/comm/DataDispatcher.cpp create mode 100644 dclasio/src/dclasio/comm/DataDispatcher.h create mode 100644 dclasio/src/dclasio/comm/DataStream.cpp create mode 100644 dclasio/src/dclasio/comm/DataStream.h create mode 100644 dclasio/src/dclasio/comm/DataTransferImpl.h create mode 100644 dclasio/src/dclasio/comm/MessageDispatcher.cpp create mode 100644 dclasio/src/dclasio/comm/MessageDispatcher.h create mode 100644 dclasio/src/dclasio/comm/MessageListener.h create mode 100644 dclasio/src/dclasio/comm/MessageQueue.cpp create mode 100644 dclasio/src/dclasio/comm/MessageQueue.h create mode 100644 dclasio/src/dclasio/comm/ResponseBuffer.cpp create mode 100644 dclasio/src/dclasio/comm/ResponseBuffer.h create mode 100644 dclasio/src/dclasio/message/BuildProgram.cpp create mode 100644 dclasio/src/dclasio/message/CommandMessage.cpp create mode 100644 dclasio/src/dclasio/message/ContextErrorMessage.h create mode 100644 dclasio/src/dclasio/message/CreateBuffer.cpp create mode 100644 dclasio/src/dclasio/message/CreateCommandQueue.cpp create mode 100644 dclasio/src/dclasio/message/CreateContext.cpp create mode 100644 dclasio/src/dclasio/message/CreateEvent.cpp create mode 100644 dclasio/src/dclasio/message/CreateKernel.cpp create mode 100644 dclasio/src/dclasio/message/CreateKernelsInProgram.cpp create mode 100644 dclasio/src/dclasio/message/CreateProgramWithSource.cpp create mode 100644 dclasio/src/dclasio/message/DeleteCommandQueue.cpp create mode 100644 dclasio/src/dclasio/message/DeleteContext.cpp create mode 100644 dclasio/src/dclasio/message/DeleteEvent.cpp create mode 100644 dclasio/src/dclasio/message/DeleteKernel.cpp create mode 100644 dclasio/src/dclasio/message/DeleteMemory.cpp create mode 100644 dclasio/src/dclasio/message/DeleteProgram.cpp create mode 100644 dclasio/src/dclasio/message/DeviceIDsResponse.h create mode 100644 dclasio/src/dclasio/message/DeviceInfosResponse.cpp create mode 100644 dclasio/src/dclasio/message/DeviceInfosResponse.h create mode 100644 dclasio/src/dclasio/message/EnqueueBarrier.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueBroadcastBuffer.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueCopyBuffer.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueMapBuffer.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueMarker.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueNDRangeKernel.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueReadBuffer.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueReduceBuffer.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueUnmapBuffer.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueWaitForEvents.cpp create mode 100644 dclasio/src/dclasio/message/EnqueueWriteBuffer.cpp create mode 100644 dclasio/src/dclasio/message/ErrorResponse.cpp create mode 100644 dclasio/src/dclasio/message/EventProfilingInfosResponse.cpp create mode 100644 dclasio/src/dclasio/message/EventSynchronizationMessage.cpp create mode 100644 dclasio/src/dclasio/message/FinishRequest.cpp create mode 100644 dclasio/src/dclasio/message/FlushRequest.cpp create mode 100644 dclasio/src/dclasio/message/GetDeviceIDs.h create mode 100644 dclasio/src/dclasio/message/GetDeviceInfo.h create mode 100644 dclasio/src/dclasio/message/GetEventProfilingInfos.cpp create mode 100644 dclasio/src/dclasio/message/GetKernelInfo.cpp create mode 100644 dclasio/src/dclasio/message/InfoResponse.cpp create mode 100644 dclasio/src/dclasio/message/Message.cpp create mode 100644 dclasio/src/dclasio/message/ProgramBuildMessage.h create mode 100644 dclasio/src/dclasio/message/ReleaseRequest.cpp create mode 100644 dclasio/src/dclasio/message/Request.cpp create mode 100644 dclasio/src/dclasio/message/Response.cpp create mode 100644 dclasio/src/dclasio/message/SetKernelArg.cpp create mode 100644 icdpp/CMakeLists.txt create mode 100644 icdpp/src/CommandQueue.cpp create mode 100644 icdpp/src/CommandQueue.h create mode 100644 icdpp/src/ComputeNode.cpp create mode 100644 icdpp/src/ComputeNode.h create mode 100644 icdpp/src/Context.cpp create mode 100644 icdpp/src/Context.h create mode 100644 icdpp/src/Device.cpp create mode 100644 icdpp/src/Device.h create mode 100644 icdpp/src/Event.cpp create mode 100644 icdpp/src/Event.h create mode 100644 icdpp/src/Kernel.cpp create mode 100644 icdpp/src/Kernel.h create mode 100644 icdpp/src/Memory.cpp create mode 100644 icdpp/src/Memory.h create mode 100644 icdpp/src/Platform.cpp create mode 100644 icdpp/src/Platform.h create mode 100644 icdpp/src/Program.cpp create mode 100644 icdpp/src/Program.h create mode 100644 icdpp/src/Retainable.cpp create mode 100644 icdpp/src/Retainable.h create mode 100644 icdpp/src/cl.cpp create mode 100644 icdpp/src/cl_khr_icd.cpp create mode 100644 icdpp/src/cl_khr_icd.h create mode 100644 icdpp/src/cl_wwu_collective.cpp create mode 100644 icdpp/src/cl_wwu_dcl.cpp create mode 100644 icdpp/src/dclicd/Buffer.cpp create mode 100644 icdpp/src/dclicd/Buffer.h create mode 100644 icdpp/src/dclicd/Error.cpp create mode 100644 icdpp/src/dclicd/Error.h create mode 100644 icdpp/src/dclicd/Event.cpp create mode 100644 icdpp/src/dclicd/Event.h create mode 100644 icdpp/src/dclicd/command/Command.cpp create mode 100644 icdpp/src/dclicd/command/Command.h create mode 100644 icdpp/src/dclicd/command/MappingCommand.cpp create mode 100644 icdpp/src/dclicd/command/MappingCommand.h create mode 100644 icdpp/src/dclicd/command/ReadWriteCommand.cpp create mode 100644 icdpp/src/dclicd/command/ReadWriteCommand.h create mode 100644 icdpp/src/dclicd/command/Readme.txt create mode 100644 icdpp/src/dclicd/detail/ContextProperties.cpp create mode 100644 icdpp/src/dclicd/detail/ContextProperties.h create mode 100644 icdpp/src/dclicd/detail/EventProfilingInfo.cpp create mode 100644 icdpp/src/dclicd/detail/EventProfilingInfo.h create mode 100644 icdpp/src/dclicd/detail/KernelArgument.cpp create mode 100644 icdpp/src/dclicd/detail/KernelArgument.h create mode 100644 icdpp/src/dclicd/detail/KernelInfo.h create mode 100644 icdpp/src/dclicd/detail/MappedMemory.h create mode 100644 icdpp/src/dclicd/detail/ProgramBuild.cpp create mode 100644 icdpp/src/dclicd/detail/ProgramBuild.h create mode 100644 icdpp/src/dclicd/detail/ProgramBuildInfo.cpp create mode 100644 icdpp/src/dclicd/detail/ProgramBuildInfo.h create mode 100644 icdpp/src/dclicd/detail/Retainable.h create mode 100644 icdpp/src/dclicd/utility.cpp create mode 100644 icdpp/src/dclicd/utility.h create mode 100644 test/CMakeLists.txt create mode 100644 test/include/boost/test/parameterized_test_ex.hpp create mode 100644 test/src/Buffer.cpp create mode 100644 test/src/CommandQueue.cpp create mode 100644 test/src/Context.cpp create mode 100644 test/src/Device.cpp create mode 100644 test/src/Event.cpp create mode 100644 test/src/Mapping.cpp create mode 100644 test/src/Memory.cpp create mode 100644 test/src/MemoryConsistency.cpp create mode 100644 test/src/Platform.cpp create mode 100644 test/src/Program.cpp create mode 100644 test/src/utility.cpp create mode 100644 test/src/utility.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9046cbc --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,86 @@ +cmake_minimum_required(VERSION 2.6) + +project(dOpenCL) + +# The following code snippet for enabling C++11 support for GCC has been taken from: +# http://stackoverflow.com/questions/12715005/add-c0x-support-in-cmake +# For other compilers, C++11 support has to enabled manually +# NOTE: Modification of CMAKE_CXX_FLAGS is not shown in ncurses UI +if(CMAKE_COMPILER_IS_GNUCXX) + execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GNUCXX_VERSION) + if(GNUCXX_VERSION VERSION_EQUAL 4.6) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + elseif(GNUCXX_VERSION VERSION_GREATER 4.6) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + else() + message(SEND_ERROR "Compiler does not support C++11") + endif() +endif(CMAKE_COMPILER_IS_GNUCXX) + +option(BUILD_UNIT_TESTS "Build dOpenCL unit tests (experimental)" OFF) + +# +# dOpenCL version information +# +# Note that the version number refers to the dOpenCL ICD, daemon, and the +# dOpenCL API. The dOpenCL library may have a different version number. +# +set(DCL_VERSION_MAJOR 0) +set(DCL_VERSION_MINOR 4) +set(DCL_VERSION_PATCH 0) +set(DCL_VERSION ${DCL_VERSION_MAJOR}.${DCL_VERSION_MINOR}.${DCL_VERSION_PATCH}) + +add_subdirectory (dclasio) +add_subdirectory (daemon) +add_subdirectory (icdpp) + +if(BUILD_UNIT_TESTS) + # enable_testing must be defined in the root CMakeLists.txt, otherwise + # 'make test' will not work correctly + enable_testing () + add_subdirectory (test) +endif(BUILD_UNIT_TESTS) + +# TODO Export targets from installation rather than build tree +#export(TARGETS dcl dOpenCL dcld FILE dOpenCL.cmake) + + +# +# package configuration +# +# TODO Add 'README_...txt' and 'INSTALL_...txt' to package +# TODO Add copyright and license header to all source files +# TODO Add dOpenCL API headers to package +# TODO Add dOpenCL API documentation to package + +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "dOpenCL is a distributed implementation of the OpenCL API.") +set(CPACK_PACKAGE_VENDOR "Group Parallel and Distributed Systems, Department of Computer Science, University of Muenster, Germany") +set(CPACK_PACKAGE_COPYRIGHT_FILE "${PROJECT_SOURCE_DIR}/COPYING") +set(CPACK_PACKAGE_VERSION_MAJOR ${DCL_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${DCL_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${DCL_VERSION_PATCH}) +set(CPACK_PACKAGE_INSTALL_DIRECTORY "dOpenCL-${DCL_VERSION_MAJOR}.${DCL_VERSION_MINOR}") +set(CPACK_PACKAGE_FILE_NAME "dOpenCL-${DCL_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}") + +# WARNING: +# CPack TGZ generator will include *all* files from the source folder by default +# Checkout a clean tree from the repository to create a source package. +set(CPACK_SOURCE_IGNORE_FILES + "/build;/.svn/;.*~$;${CPACK_SOURCE_IGNORE_FILES}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "dOpenCL-${DCL_VERSION}-src") +set(CPACK_SOURCE_STRIP_FILES TRUE) + +if(UNIX) +set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README_Linux.txt") +set(CPACK_GENERATOR "TGZ") +set(CPACK_SOURCE_GENERATOR "TGZ") +endif(UNIX) +if(WIN32) +set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README_Win.txt") +set(CPACK_GENERATOR "ZIP") +set(CPACK_SOURCE_GENERATOR "ZIP") +endif(WIN32) + +# CPack must be included *after* the CPack configuration +include(CPack) + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/COPYING.academic b/COPYING.academic new file mode 100644 index 0000000..070089f --- /dev/null +++ b/COPYING.academic @@ -0,0 +1,37 @@ +dOpenCL Academic License - Version 1.0 - June 30th, 2013 + +Developed by: Research Group Parallel and Distributed Systems + Department of Mathematics and Computer Science + University of Muenster, Germany + http://dopencl.uni-muenster.de + + Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal with the Software in an academic environment for research or +teaching purposes without any monetary gain, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense +and to permit persons to whom the Software is furnished to do so, subject +to the following conditions: + + Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. + + Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimers in the documentation +and/or other materials provided with the distribution. + + Neither the names of the above listed research groups, nor the names of +its contributors may be used to endorse or promote products derived from +this Software without specific prior written permission. + + This Software and its authors have to be cited in publications related to +products using this Software or products derived from this Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE. + diff --git a/INSTALL_Linux.txt b/INSTALL_Linux.txt new file mode 100644 index 0000000..b4d9cd1 --- /dev/null +++ b/INSTALL_Linux.txt @@ -0,0 +1,116 @@ +Installing dOpenCL +================== + +(last update: 2014-12-22, Philipp Kegel) + +1. Requirements +2. Building dOpenCL from source +3. Installing dOpenCL +4. Known issues + + +------------ +Requirements +------------ + +* C++11-enabled compiler + has been tested successfully with g++ 4.6 and g++ 4.7 +* OpenCL 1.1+ + only has to be installed on the dOpenCL compute nodes. + The OpenCL headers and C++ binding have to be installed in the system's + default include directories +* Boost (>=1.41.0) + required libraries: Boost.Asio, Boost.Program_options, Boost.Test (optional) + http://www.boost.org +* CMake (>=2.6) + http://www.cmake.org + + +---------------------------- +Building dOpenCL from source +---------------------------- + +1. Create dOpenCL home + + Create a directory and copy the dOpenCL sources into that directory. + This directory will become the dOpenCL home. + +2. Build dOpenCL + + dOpenCL is build in two steps: after creating a Make file using CMake, the + dOpenCL binaries and libraries are build using Make. + + a) Creating the make file using CMake + The dOpenCL CMake configuration (CMakeLists.txt in dOpenCL home) allows + for the following settings: + + FORCE_FLUSH=OFF flush command queues after enqueing a command + This option can be set to increase concurrency of command execution + in OpenCL implementations that do not execute command before a + command queue is flushed (e.g., AMD APP SDK) + BUILD_SHARED_LIBS=ON + build dOpenCL communication library as shared object (recommended) + Note that the dOpenCL installable client driver (libdOpenCL.so) is + always built as a shared object. + + Besides, the CMake build type (CMAKE_BUILD_TYPE) has to be specified. + We recommend using the ncurses CMake GUI 'ccmake'. + + We strongly recommend to perform an out-of-source build: create a + directory for building dOpenCL and change into that directory. For + example, create a subdirectory 'build' inside the dOpenCL home. + + b) Build dOpenCL binaries and libraries using Make + After creating the make file with CMake, the dOpenCL binaries and + libraries can be built by calling 'make' in the build directory. + + The corresponding commands for building dOpenCL are as follows: + cd + mkdir build + cd build + cmake -D CMAKE_BUILD_TYPE=Release .. + make + + +------------------ +Installing dOpenCL +------------------ + +dOpenCL is most easily installed by calling 'make install' from within the build +directory. This will install dOpenCL in your system's default directory. Note +that the call requires root rights. + +If you do not want to install dOpenCL into your default system directory, or if +you do not have appropriate rights to do so, you should export the DCL_HOME +environment variable, such that its value is the path to the dOpenCL build +directory. + +After installing dOpenCL, refer to README_Linux.txt for information on how to +use dOpenCL. + +Installable Client Driver (ICD) +------------------------------- + +dOpenCL currently does not support OpenCL's ICD loader mechanism. Hence, either +the system's ICD loader (/libOpenCL.so) has to be +replaced by dOpenCL's ICD (libdOpenCL.so), or the dOpenCL ICD has to be added to +the list of preloaded libraries in the LD_PRELOAD environment variable. + + +------------ +Known issues +------------ + +* GNU C++ linker: undefined reference to `pthread_*' + +Although dOpenCL does not use POSIX threads directly (but C++11 threads) +compilers may use POSIX threads to implement C++11 threads. This is the case for +the GNU C++ compiler, which requires the '-pthread' compiler option in order to +compile dOpenCL. This option can be set using the CMAKE_CXXFLAGS setting in CMake. + +* CMake: Boost_DIR always is set to Boost_DIR-NOTFOUND + +This is a known bug of the FindBoost CMake module (see +http://public.kitware.com/Bug/view.php?id=13453). The problem can be ignored as +CMake stills correctly finds the Boost directory (if Boost is installed). + diff --git a/README_Linux.txt b/README_Linux.txt new file mode 100644 index 0000000..247f4ad --- /dev/null +++ b/README_Linux.txt @@ -0,0 +1,219 @@ +dOpenCL +======= + +(last update: 2014-12-22, Philipp Kegel) + +dOpenCL (distributed Open Compute Language) is an implementation of the OpenCL +API for distributed systems created by Philipp Kegel with the help of Michel +Steuwer, Sergei Gorlatch, and several students. + +References: +* Kegel, P., Steuwer, M., Gorlatch, S., 2012. dOpenCL: Towards a Unified + Programming Approach for Distributed Heterogeneous Multi-/Many-Core Systems. + + +-------- +Contents +-------- + +1. System requirements +2. Getting started +3. Project structure +4. Known issues +5. Contact + + +------------------- +System requirements +------------------- + +See 'INSTALL_Linux.txt' for system requirements and installation instructions. + +dOpenCL has been successfully tested on the following systems: + +* Ubuntu 12.04 +* CentOS 5.6, 5.9 +* Scientific Linux 5.6 + + +--------------- +Getting started +--------------- + +Before running the dOpenCL daemon or your OpenCL application, you have to ensure +that dOpenCL is properly installed (see 'INSTALL_Linux.txt'). + +Setting up your environment (optional) +-------------------------------------- + +Unless dOpenCL has been installed into your default system directories, you have +you have to update your environment's PATH and LD_LIBRARY_PATH as follows (note +the use of the DCL_HOME environment variable): + + export PATH=$PATH:$DCL_HOME/daemon + export LD_LIBRARY_PATH=$DCL_HOME/dclgcf:$DCL_HOME/icdpp:$LD_LIBRARY_PATH + +Starting and stopping the dOpenCL daemon +---------------------------------------- + +In order to start the dOpenCL daemon you need to have an OpenCL 1.1+ compliant +OpenCL implementation installed on your system. + +The dOpenCL daemon has to be started on all nodes that should be accessible via +dOpenCL. Currently, the daemon does not become a daemon process but blocks the +terminal. + + dcld [-p] [:] + +Hint: Ubuntu resolves all hostnames of the local system to the address of the +loopback interface. In order to bind the dOpenCL daemon to another interface, +the interface's IP address has to be provided rather than the interface's host +name. + +The -p option selects the native OpenCL platform that should be used by the +dOpenCL daemon. The specified platform name must be part of the platform's full +name. If no platform is specified, the system's OpenCL platform is used. + +The daemon is stopped by sending it a SIGINT (press Strg+C) or SIGTERM (kill) +signal. + +Running an OpenCL application with dOpenCL +------------------------------------------ + +As dOpenCL *is* an OpenCL implementation, existing applications do not have to +be compiled or linked anew in order to use dOpenCL. However, the following +preparations are required to connect the host and daemons an to make the +application use the dOpenCL ICD. + +1. Create a node file + + Create a file named 'dcl.nodes' *in your application's working directory.* + Add a line with a host name and optional port number (in the format + [:]) for each node of your network, on which a dOpenCL + daemon is running. For example: + + echo localhost >> dcl.nodes + + You can also create a global node file anywhere in your systems and export + the DCL_NODE_FILE environment variable. If DCL_NODE_FILE is defined and not + empty, its value is taken as the location of the application's node file. + The 'dcl.nodes' file in the application's working directory will be ignored + in this case. + +2. Run the application + + If you have replaced the system's ICD by dOpenCL's ICD, you may run your + application as usual. + + Otherwise, you have to use the LD_PRELOAD environment variable in order to + preload the dOpenCL ICD before running your OpenCL application: + + LD_PRELOAD=libdOpenCL.so [] + + To avoid explicitly setting this variable each time you run your application, + you may export LD_PRELOAD to your environment: + + export LD_PRELOAD="$LD_PRELOAD libdOpenCL.so" + + We recommend to create a start script for you application which you use to + export LD_PRELOAD (and LD_LIBRARY_PATH as described in 'Setting up your + environment') before starting you application. + +Controlling log output +---------------------- + +dOpenCL creates log files for debugging purposes. In the daemon's working +directory, a file named 'dcl_.log' is created, where will +be the host name you selected when starting the damon. In the application's +working directory, a file 'dcl_host.log' will be created. + +Currently, logging cannot be switched off, but the amount of log messages can be +controlled by setting the log level in the DCL_LOG_LEVEL environment variable. +The following settings are eligible: + + ERROR only log error messages + WARNING log warnings + INFO log info messages (default for release build) + DEBUG log debug messages (default for debug build) + VERBOSE log everything + +If no log level is specified, the default log level is selected. + +Note that the log files are deleted each time the daemon or application is +restarted. + + +----------------- +Project structure +----------------- + +/ ++- dcl dOpenCL API definitions +| +- doc Doxygen documentation of dOpenCL API +| +- include +| | +- CL OpenCL API extension +| | | cl_wwu_collective.h collective operations +| | | cl_wwu_dcl.h distributed OpenCL +| | +- dcl dOpenCL API headers +| | ComputeNode.h +| | CommunicationManager.h +| | Device.h +| | Host.h +| | ... ++- dclasio dOpenCL API implementation using Boost.Asio ++- icdpp ICD implementation (C++, Boost.Asio only) +| implements OpenCL (including API extension) using dOpenCL API ++- daemon dOpenCL daemon ++- test Test suite (based on Boost Test Library, experimental) + + +------------ +Known Issues +------------ + +* dOpenCL does not yet support the OpenCL ICD loader mechanism. + Hence, dOpenCL has to be preloaded using LD_PRELOAD to override the system's + ICD loader or OpenCL implementation. + +* In most cases, the dOpenCL daemon will crash if a host is disconnected (e.g., + due to an application failure) during a running data transfer. + +* Programs currently cannot be built from binaries or built-in kernels (OpenCL + 1.2) + +* Programs are always build synchronously; callbacks are supported though + +* #include directives in OpenCL C programs are currently not supported + +* dOpenCL does not support the following OpenCL APIs, but will support them in + future releases: + + all image and sampler APIs + + all sub-buffer APIs + + vendor-specific extensions (e.g., device fission) + + all sub-device APIs (OpenCL 1.2) + + clGetKernelArgInfo (OpenCL 1.2) + + cl{Compile|Link}Program (OpenCL 1.2) + + clEnqueue{Read|Write|Copy}BufferRect (OpenCL 1.2) + + clEnqueueFillBuffer (OpenCL 1.2) + + clEnqueueMigrateMemObject (OpenCL 1.2) + +* dOpenCL does not and will not support the following OpenCL APIs: + + OpenGL/CL or DirectX/CL interop + + native kernels (clEnqueueNativeKernel is implemented but always returns + CL_INVALID_OPERATION) + + OpenCL 1.0 deprecated APIs + +* dOpenCL collective operation APIs are not yet available + +* Communication between nodes in dOpenCL is not secured in any way. + +* Nodes in dOpenCL should all use the same byte order. + + +------- +Contact +------- + +If you have any questions or suggestions regarding dOpenCL feel free to contact +me via email (philipp.kegel@uni-muenster.de). + diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt new file mode 100644 index 0000000..837907e --- /dev/null +++ b/daemon/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 2.6) + +project(dOpenCLdaemon) + +option(FORCE_FLUSH "Force flush after enqueued command (recommended for AMD OpenCL runtime)" OFF) + +set(DOPENCL_INCLUDE_DIR "${dOpenCLlib_SOURCE_DIR}/include" CACHE PATH "Path to dOpenCL headers") +set(DOPENCL_LIBRARY_DIR "${dOpenCLlib_BINARY_DIR}" CACHE PATH "Path to dOpenCL library") + +# search for Boost.Program_options +find_package(Boost 1.41.0 COMPONENTS program_options REQUIRED) + +file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src *.cpp) +#aux_source_directory(${PROJECT_SOURCE_DIR}/src SOURCES) + +include_directories(${DOPENCL_INCLUDE_DIR} + ${Boost_INCLUDE_DIRS}) + +link_directories(${DOPENCL_LIBRARY_DIR} + ${Boost_LIBRARY_DIRS}) + + +# +# dOpenCL daemon target +# + +add_executable (dcld ${SOURCES}) +target_link_libraries(dcld + dcl + OpenCL + ${Boost_LIBRARIES}) + +# enable OpenCL 1.1 compatibility +set_property(TARGET dcld + PROPERTY COMPILE_DEFINITIONS + CL_USE_DEPRECATED_OPENCL_1_1_APIS) +if (FORCE_FLUSH) +set_property(TARGET dcld + APPEND PROPERTY COMPILE_DEFINITIONS + FORCE_FLUSH) +endif (FORCE_FLUSH) + + +# +# install configuration +# + +install(TARGETS dcld + DESTINATION bin) + diff --git a/daemon/src/CommandQueue.cpp b/daemon/src/CommandQueue.cpp new file mode 100644 index 0000000..4a29cc3 --- /dev/null +++ b/daemon/src/CommandQueue.cpp @@ -0,0 +1,965 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandQueue.cpp + * + * \date 2012-08-12 + * \author Philipp Kegel + */ + +#include "CommandQueue.h" + +#include "Context.h" +#include "Device.h" +#include "Event.h" +#include "Kernel.h" +#include "Memory.h" + +#include "command/Command.h" +#include "command/CopyDataCommand.h" +#include "command/SetCompleteCommand.h" + +#include +#include +#include +#include + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +namespace { + +/*! + * \brief Callback used to execute enqueued commands. + */ +void executeCommand(cl_event event, cl_int execution_status, void *user_data) { + std::unique_ptr command(static_cast(user_data)); + assert(command != nullptr); + command->execute(execution_status); +} + +#ifdef PROFILE +/*! + * \brief Callback used to log event profiling info. + */ +void logEventProfilingInfo(cl_event object_, cl_int execution_status, void *user_data) { + std::unique_ptr str(static_cast(user_data)); + cl::Event event; + cl_int err; + + /* assign event to C++ wrapper */ + event() = object_; + err = ::clRetainEvent(object_); + assert(err == CL_SUCCESS); + + /* query profiling info */ + try { + cl_ulong queued, submit, start, end; + + event.getProfilingInfo(CL_PROFILING_COMMAND_QUEUED, &queued); + event.getProfilingInfo(CL_PROFILING_COMMAND_SUBMIT, &submit); + event.getProfilingInfo(CL_PROFILING_COMMAND_START, &start); + event.getProfilingInfo(CL_PROFILING_COMMAND_END, &end); + + dcl::util::Logger << dcl::util::Debug + << "Command completed (" << (str ? *str : "") << ")\n" + << "\tqueued =" << queued << '\n' + << "\tsubmit =" << submit << '\n' + << "\tstart =" << start << '\n' + << "\tend =" << end << '\n' + << "\tdurance=" << (static_cast(end - start) / 1000000000.0) << " sec" + << std::endl; + } catch (const cl::Error& err) { + dcl::util::Logger << dcl::util::Error + << "OpenCL error (ID=" << err.err() << "): " << err.what() + << std::endl; + } +} +#endif + +cl::NDRange createNDRange(const std::vector& vector) { + switch (vector.size()) { + case 0: + return cl::NullRange; + case 1: + return cl::NDRange(vector[0]); + case 2: + return cl::NDRange(vector[0], vector[1]); + case 3: + return cl::NDRange(vector[0], vector[1], vector[2]); + default: + throw cl::Error(CL_INVALID_WORK_DIMENSION); + } +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dcld { + +CommandQueue::CommandQueue( + const std::shared_ptr& context, + Device *device, + cl_command_queue_properties properties) : + _context(context) { + if (!context) throw cl::Error(CL_INVALID_CONTEXT); + if (!device) throw cl::Error(CL_INVALID_DEVICE); + _commandQueue = cl::CommandQueue(*context, *device, properties); +} + +CommandQueue::~CommandQueue() { } + +/*! + * \brief Returns the native command queue. + */ +CommandQueue::operator cl::CommandQueue() const { + return _commandQueue; +} + +/* + * INFO: Synchronization + * + * Synchronization always is based on events in a wait list which act as + * synchronization points (the only exception is the enqueueBarrier command). + * For events associated with a command on the same compute node and for user + * events, this requires no special measures; the events are just passed to the + * implementation. But for events which are associated with a command on another + * compute node (instances of dcld::EventListener), a synchronization across + * compute nodes is required, if a memory object is associated with such an + * event. + * For each associated memory object, a data transfer from the memory object's + * owner (the compute node that executes the command associated with the event) + * is enqueued to this command queue. A native event is created for each data + * transfer. + * While the associated memory objects are removed from the event, the native + * events associated with the data transfers are added to it. Thus, + * synchronization is only enqueued once to the command queue that first uses + * this event for synchronization. + * The native events that have been added (associated) with the event during + * synchronization are added to the native event wait list, such that the OpenCL + * implementation synchronizes the memory objects. This is particularly + * important if the event is used by another command queue on the same compute + * node: while the data has already been transferred to the compute node, it is + * only visible to the device that performed the synchronization. Thus, all + * other devices have to synchronize in order to obtain the data. + */ +void CommandQueue::synchronize( + const std::vector>& eventWaitList, + VECTOR_CLASS& nativeEventWaitList) { + bool synchronizationPending = false; + + nativeEventWaitList.clear(); + + if (eventWaitList.empty()) return; + + dcl::util::Logger << dcl::util::Debug + << "Synchronizing event wait list with " << eventWaitList.size() + << " event(s)" << std::endl; + + for (auto event : eventWaitList) { + /* TODO Create Event::synchronize method + * Rather than checking if an event is of type RemoteEvent before + * calling synchronize, make synchronize a member of all event classes + * that returns a list native events for local events and performs + * synchronization for remote events */ + auto remoteEvent = std::dynamic_pointer_cast(event); + if (remoteEvent) { // event is a remote event + VECTOR_CLASS synchronizeEvents; + remoteEvent->synchronize(_commandQueue, synchronizeEvents); + /* FIXME Only synchronize memory objects once if associated with multiple events in wait list + * Different events may be associated with the same memory object + * However, a memory object must only be synchronized once. + * Synchronizing with multiple events associated with the same memory + * object may be considered undefined behavior. */ + nativeEventWaitList.insert(std::end(nativeEventWaitList), + std::begin(synchronizeEvents), std::end(synchronizeEvents)); + + synchronizationPending = true; + } else { // event is a local event + auto eventImpl = std::dynamic_pointer_cast(event); + if (!eventImpl) throw cl::Error(CL_INVALID_EVENT_WAIT_LIST); + nativeEventWaitList.push_back(*eventImpl); + } + } + + if (synchronizationPending) { + /* Flush the command queue to ensure instant execution of the acquire + * operation */ + _commandQueue.flush(); + } +} + +void CommandQueue::enqueueReadBuffer( + const std::shared_ptr& buffer, + bool blocking, + size_t offset, + size_t size, + const VECTOR_CLASS& nativeEventWaitList, + dcl::object_id commandId, + cl::Event& mapData, cl::Event& unmapData) { + cl::UserEvent copyData(*_context); + + // enqueue map buffer (implicit download) + void *ptr = _commandQueue.enqueueMapBuffer( + *buffer, + CL_FALSE, // non-blocking map + CL_MAP_READ, // map for reading + offset, size, + (nativeEventWaitList.empty() ? nullptr : &nativeEventWaitList), + &mapData); +#ifdef PROFILE + mapData.setCallback(CL_COMPLETE, &logEventProfilingInfo, new std::string("map buffer for reading")); +#endif + // enqueue unmap buffer + VECTOR_CLASS unmapEventWaitList(1, copyData); + _commandQueue.enqueueUnmapMemObject( + *buffer, + ptr, + &unmapEventWaitList, &unmapData); +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#else + if (blocking) { + _commandQueue.flush(); + } +#endif + + try { + // schedule data transfer + mapData.setCallback(CL_COMPLETE, &executeCommand, + new command::CopyDataCommand( + _context->host(), commandId, size, ptr, copyData)); + /* The read buffer command is finished on the host, such that no + * 'command complete' message must be sent by the compute node. */ + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } +} + +void CommandQueue::enqueueWriteBuffer( + const std::shared_ptr& buffer, + bool blocking, + size_t offset, + size_t size, + const VECTOR_CLASS& nativeEventWaitList, + dcl::object_id commandId, + cl::Event& mapData, cl::Event& unmapData) { + cl::UserEvent copyData(*_context); + + // enqueue map buffer + /* !!! WARNING !!! + * NVIDIA only: the reference count of events in wait list is *not* + * increased by clEnqueueMapBuffer. This may be a bug, if the event is not + * retained by other means than its reference count. + * !!!!!!!!!!!!!!! */ + void *ptr = _commandQueue.enqueueMapBuffer( + *buffer, + CL_FALSE, // non-blocking map + CL_MAP_WRITE, // map for writing + offset, size, + (nativeEventWaitList.empty() ? nullptr : &nativeEventWaitList), + &mapData); + // enqueue unmap buffer (implicit upload) + VECTOR_CLASS unmapEventWaitList(1, copyData); + /* !!! WARNING !!! + * NVIDIA only: the reference count of copyData is *not* increased by + * clEnqueueUnmapMemObject. This may be a bug, if the event is not retained + * by other means than its reference count. + * !!!!!!!!!!!!!!! */ +// std::cout << "!!! before unmap copyData refCount=" << copyData.getInfo() << std::endl; +// ::clRetainEvent(copyData()); // tentative fix for NVIDIA + _commandQueue.enqueueUnmapMemObject( + *buffer, + ptr, + &unmapEventWaitList, &unmapData); +// std::cout << "!!! after unmap copyData refCount=" << copyData.getInfo() << std::endl; +#ifdef PROFILE + unmapData.setCallback(CL_COMPLETE, &logEventProfilingInfo, new std::string("unmap buffer after writing")); +#endif +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#else + if (blocking) { + _commandQueue.flush(); + } +#endif + + try { + // schedule data transfer + mapData.setCallback(CL_COMPLETE, &executeCommand, + new command::CopyDataCommand( + _context->host(), commandId, size, ptr, copyData)); + // schedule completion message for host + /* A 'command complete' message is sent to the host. + * Note that this message must also be sent, if no event is associated + * with this command, such that a blocking write succeeds. */ + unmapData.setCallback(CL_COMPLETE, &executeCommand, + new command::SetCompleteCommand(_context->host(), commandId, cl::UserEvent(*_context))); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } +} + +void CommandQueue::enqueuePhonyMarker( + bool blocking, + const VECTOR_CLASS& nativeEventWaitList, + dcl::object_id commandId, cl::Event& marker) { +#if defined(CL_VERSION_1_2) + _commandQueue.enqueueMarkerWithWaitList(&nativeEventWaitList, &marker); +#else // #if defined(CL_VERSION_1_2) + if (nativeEventWaitList.empty()) { + _commandQueue.enqueueMarker(&marker); + } else { + /* TODO Use pre-OpenCL 1.2 APIs to implement CommandQueue::enqueueMarker with wait list + * clEnqueueMarker (deprecated) does not support an event list. */ + assert(!"clEnqueueMarker does not support event wait list"); + } +#endif // #if defined(CL_VERSION_1_2) +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#else + if (blocking) { + _commandQueue.flush(); + } +#endif + + try { + // schedule completion message for host + /* A 'command complete' message is sent to the host. + * Note that this message must also be sent, if no event is associated + * with this command, such that a blocking operation succeeds. */ + marker.setCallback(CL_COMPLETE, &executeCommand, + new command::SetCompleteCommand(_context->host(), commandId, cl::UserEvent(*_context))); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } +} + +void CommandQueue::flush() { + _commandQueue.flush(); +} + +/* clFinish is a synchronization point */ +void CommandQueue::finish() { + _commandQueue.finish(); + + /* TODO Implement synchronization for clFinish + * It is not clear from the specification what this means; maybe it acts as + * an active release, i.e., the memory objects modified by this command queue + * are replicated to all other compute nodes. */ +} + +void CommandQueue::enqueueCopyBuffer( + const std::shared_ptr& src, + const std::shared_ptr& dst, + size_t srcOffset, + size_t dstOffset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr *event) { + auto srcImpl = std::dynamic_pointer_cast(src); + auto dstImpl = std::dynamic_pointer_cast(dst); + VECTOR_CLASS nativeEventWaitList; + cl::Event copyBuffer; + + if (!srcImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + if (!dstImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + + /* Enqueue copy buffer + * Only create event if requested by caller */ + _commandQueue.enqueueCopyBuffer( + *srcImpl, *dstImpl, + srcOffset, dstOffset, size, + &nativeEventWaitList, event ? ©Buffer : nullptr); +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#endif + + if (event) { // an event should be associated with this command + try { + *event = std::make_shared(commandId, _context, dstImpl, copyBuffer); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } +} + +void CommandQueue::enqueueReadBuffer( + const std::shared_ptr& buffer, + bool blockingRead, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr *event) { + auto bufferImpl = std::dynamic_pointer_cast(buffer); + VECTOR_CLASS nativeEventWaitList; + cl::Event mapData, unmapData; + cl::UserEvent copyData(*_context); + + if (!bufferImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + + /* Enqueue map buffer (implicit download) */ + void *ptr = _commandQueue.enqueueMapBuffer( + *bufferImpl, + CL_FALSE, // non-blocking map + CL_MAP_READ, // map for reading + offset, size, + &nativeEventWaitList, &mapData); + /* Enqueue unmap buffer + * Only create a native event for unmapping, if an event should be + * associated with this read buffer command */ + nativeEventWaitList.assign(1, copyData); + _commandQueue.enqueueUnmapMemObject( + *bufferImpl, + ptr, + &nativeEventWaitList, event ? &unmapData : nullptr); +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#else + if (blockingRead) { + _commandQueue.flush(); + } +#endif + + try { + /* Schedule data sending + * A 'command submitted' message will be sent to the host in order to + * start data receipt. */ + mapData.setCallback(CL_COMPLETE, &executeCommand, + new command::CopyDataCommand( + _context->host(), commandId, size, ptr, copyData)); + /* The read buffer command is finished on the host such that no 'command + * complete' message must be sent by the compute node. */ + + if (event) { // an event should be associated with this command + /* WARNING: No callback must be registered for any native event of + * the ReadMemoryEvent object, that access the object. As the host + * finishes the read buffer command, the application may delete the + * ReadMemoryEvent object, while or even *before* the callbacks are + * processed. Thus, a callback that accesses the ReadMemoryEvent + * object may raise a SIGSEGV. */ + *event = std::make_shared(commandId, _context, + mapData, unmapData); + } + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } +} + +void CommandQueue::enqueueWriteBuffer( + const std::shared_ptr& buffer, + bool blockingWrite, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr *event) { + auto bufferImpl = std::dynamic_pointer_cast(buffer); + VECTOR_CLASS nativeEventWaitList; + cl::Event mapData, unmapData; + cl::UserEvent copyData(*_context); + + if (!bufferImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + + /* Enqueue map buffer */ + void *ptr = _commandQueue.enqueueMapBuffer( + *bufferImpl, + CL_FALSE, // non-blocking map + CL_MAP_WRITE, // map for writing + offset, size, + &nativeEventWaitList, &mapData); + /* Enqueue unmap buffer (implicit upload) */ + nativeEventWaitList.assign(1, copyData); + _commandQueue.enqueueUnmapMemObject( + *bufferImpl, + ptr, + &nativeEventWaitList, &unmapData); +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#else + if (blockingWrite) { + _commandQueue.flush(); + } +#endif + + try { + /* TODO Sketch of a possible solution for a command-based implementation + * Complex commands, i.e., commands which include interaction with the + * host, should be implemented by a class and must be independent of an + * event. */ +#if 0 + /* The write buffer command notifies the host about its submission and + * completion, regardless an event is associated with it or not. */ + std::shared_ptr writeBuffer( + std::make_shared(_context->host(), + commandId, size, ptr, mapBuffer, dataReceipt, unmapData)); + + if (event) { // an event should be associated with this command + /* An event wrapper retains its associated command for further + * commands from the host. Moreover, it broadcast command execution + * status changes to other compute nodes in the command's context, + * while the command only communicates with the host. */ + *event = std::make_shared(commandId, _context, + bufferImpl, writeBuffer); + } +#else + /* Schedule data receipt + * A 'command submitted' message will be sent to the host. */ + mapData.setCallback(CL_COMPLETE, &executeCommand, + new command::CopyDataCommand( + _context->host(), commandId, size, ptr, copyData)); + /* Schedule completion message for host + * A 'command complete' message is sent to the host. + * Note that this message must also be sent, if no event is associated + * with this command, such that a blocking write succeeds. */ + unmapData.setCallback(CL_COMPLETE, &executeCommand, + new command::SetCompleteCommand(_context->host(), commandId, cl::UserEvent(*_context))); + + if (event) { // an event should be associated with this command + /* This event must only broadcast its status on other compute nodes + * but not to the host, as a 'command complete' message is already + * sent to the host by the callback that has been set for the native + * event unmapData. */ + /* FIXME Avoid race condition in write buffer command + * Callbacks are registered for unmapData to 1) notify the host + * about command completion, and 2) to synchronize the memory object + * associated with WriteMemoryEvent. + * As the execution order of callback is unspecified, the host may + * be notified about command completion (callback 1) before + * callback 2 is executed. If the application and the network + * respond quickly to callback 1 in order to delete the + * WriteMemoryEvent object, it may be deleted *before* callback 2 is + * processed. In this case callback 2 tries to access the deleted + * WriteMemoryEvent object, such that a SIGSEGV will be raised. */ + *event = std::make_shared(commandId, _context, + bufferImpl, mapData, unmapData); + } +#endif + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } +} + +void CommandQueue::enqueueMapBuffer( + const std::shared_ptr& buffer, + bool blockingMap, + cl_map_flags map_flags, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr *event) { + auto bufferImpl = std::dynamic_pointer_cast(buffer); + VECTOR_CLASS nativeEventWaitList; + + if (!bufferImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + + if (map_flags & CL_MAP_READ) { + /* The mapped memory region has to be synchronized, i.e., it has to be + * downloaded to the mapped host pointer. */ + cl::Event mapData, unmapData; + + enqueueReadBuffer(bufferImpl, blockingMap, offset, size, + nativeEventWaitList, commandId, mapData, unmapData); + + if (event) { // an event should be associated with this command + /* The event must only broadcast its status on other compute nodes + * but not to the host, as a 'command complete' message will be sent + * to the host by the callback that has been set for the native + * event unmapData. */ + /* WARNING: No callback must be registered for any native event of + * the CompoundNodeEvent object, that access the object. As the order + * of execution of callbacks is undefined, the application may delete + * the CompoundNodeEvent object, while the callbacks are processed. + * Thus, a callback that accesses the CompoundNodeEvent object may + * raise a SIGSEGV. */ + try { + *event = std::make_shared(commandId, _context, + mapData, unmapData); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } + } else { + /* The mapped memory region has *not* to be synchronized, as it will not + * be read. */ + cl::Event marker; + + enqueuePhonyMarker(blockingMap, nativeEventWaitList, commandId, marker); + + if (event) { // an event should be associated with this command + /* This event must only broadcast its status on other compute nodes + * but not to the host, as a 'command complete' message is already + * sent to the host by the callback that has been set for the native + * event marker. */ + /* WARNING: No callback must be registered for the native event of + * the SimpleNodeEvent object, that access the object. As the order + * of execution of callbacks is undefined, the application may delete + * the SimpleNodeEvent object, while the callbacks are processed. + * Thus, a callback that accesses the SimpleNodeEvent object may + * raise a SIGSEGV. */ + try { + *event = std::make_shared(commandId, _context, marker); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } + } +} + +void CommandQueue::enqueueUnmapBuffer( + const std::shared_ptr& buffer, + cl_map_flags map_flags, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr *event) { + auto bufferImpl = std::dynamic_pointer_cast(buffer); + VECTOR_CLASS nativeEventWaitList; + + if (!bufferImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + + if (map_flags & CL_MAP_WRITE) { + /* The mapped memory region has to be synchronized, i.e. its data + * has to be uploaded to the buffer. */ + cl::Event mapData, unmapData; + + enqueueWriteBuffer(bufferImpl, false, offset, size, + nativeEventWaitList, commandId, mapData, unmapData); + + if (event) { // an event should be associated with this command + /* The event must only broadcast its status on other compute nodes + * but not to the host, as a 'command complete' message will be sent + * to the host by the callback that has been set for the native + * event unmapData. */ + try { + *event = std::make_shared(commandId, _context, + bufferImpl, mapData, unmapData); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } + } else { + /* The mapped memory region has *not* to be synchronized, as it has + * not been written. */ + cl::Event marker; + + enqueuePhonyMarker(false, nativeEventWaitList, commandId, marker); + + if (event) { // an event should be associated with this command + /* The event must only broadcast its status on other compute nodes + * but not to the host, as a 'command complete' message will be sent + * to the host by the callback that has been set for the native + * event marker. */ + /* WARNING: No callback must be registered for the native event of + * the SimpleNodeEvent object, that access the object. As the order + * of execution of callbacks is undefined, the application may delete + * the SimpleNodeEvent object, while the callbacks are processed. + * Thus, a callback that accesses the SimpleNodeEvent object may + * raise a SIGSEGV. */ + try { + *event = std::make_shared(commandId, _context, marker); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } + } +} + +void CommandQueue::enqueueNDRangeKernel( + const std::shared_ptr& kernel, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr *event) { + auto kernelImpl = std::dynamic_pointer_cast(kernel); + VECTOR_CLASS nativeEventWaitList; + cl::Event ndRangeKernel; + + if (!kernelImpl) throw cl::Error(CL_INVALID_KERNEL); + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + + /* Enqueue ND range kernel + * Only create event if requested by caller */ + _commandQueue.enqueueNDRangeKernel( + *kernelImpl, + createNDRange(offset), createNDRange(global), createNDRange(local), + &nativeEventWaitList, event ? &ndRangeKernel : nullptr); +#ifdef FORCE_FLUSH + _commandQueue.flush(); +#endif + + if (event) { // an event should be associated with this command + try { + *event = std::make_shared(commandId, _context, + kernelImpl->writeMemoryObjects(), ndRangeKernel); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } +} + +/* + * The semantics of enqueueMarker is unclear: + * What is clEnqueueMarkerWithWaitList good for, if no event is returned? + */ +void CommandQueue::enqueueMarker( + const std::vector> *eventWaitList, + dcl::object_id commandId, std::shared_ptr *event) { + VECTOR_CLASS nativeEventWaitList; + cl::Event marker; + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + +#if defined(CL_VERSION_1_2) + /* Use native enqueueMarkerWithWaitList */ + _commandQueue.enqueueMarkerWithWaitList( + &nativeEventWaitList, event ? &marker : nullptr); +#else // #if defined(CL_VERSION_1_2) + if (eventWaitList) { + /* TODO Use pre-OpenCL 1.2 APIs to implement CommandQueue::enqueueMarker with wait list + * clEnqueueMarker (deprecated) does not support an event list. */ + assert(!"clEnqueueMarkerWithWaitList not implemented"); +#if 0 + /* TODO Use count-down latch to implement clEnqueueMarkerWithWaitList + * Each event in wait list decrements the latch once. When the latch is + * decremented to 0 (triggered), it sets the marker to complete. The + * event which triggered the latch also deletes it. + * To ensure in-order execution (for in-order command-queues), a marker + * is enqueued and added to the event wait list. */ + /* WARNING: The marker event is implemented by a user event. As such it + * cannot be used in the event list of clEnqueueWaitForEvents. Hence, + * clEnqueueMarkerWithWaitList cannot be fully implemented using the + * OpenCL 1.1 APIs. */ + cl::UserEvent complete; + + if ((_commandQueue.getInfo() & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)) { + cl::Event execution; + _commandQueue.enqueueMarker(&execution); + nativeEventWaitList.push_back(execution); + } + + auto cdl = new CountDownLatch(nativeEventWaitList.size(), + std::bind(&cl::UserEvent::setStatus, complete, CL_COMPLETE)); + for (auto nativeEvent : nativeEventWaitList) { + nativeEvent->setCallback(CL_COMPLETE, &countDown, cdl); + } + + marker = complete; // downcast marker to cl::Event +#endif + } else { + _commandQueue.enqueueMarker(&marker); + } +#endif // #if defined(CL_VERSION_1_2) + + if (event) { // an event should be associated with this command + try { + *event = std::make_shared(commandId, _context, marker); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } +} + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +void CommandQueue::enqueueWaitForEvents( + const std::vector>& eventList) { + VECTOR_CLASS nativeEventList; + + assert(!eventList.empty()); // event list must no be empty + + dcl::util::Logger << dcl::util::Debug + << "Synchronizing event list with " << eventList.size() << " event(s)" + << std::endl; + + /* Obtain native event list + * Unlike other enqueued commands, wait-for-events throws CL_INVALID_EVENT, + * rather than CL_INVALID_EVENT_WAIT_LIST, if the event list contains an + * invalid event. */ + for (auto event : eventList) { + /* TODO Create Event::synchronize method (see CommandQueue::synchronize) */ + auto remoteEvent = std::dynamic_pointer_cast(event); + if (remoteEvent) { // event is a remote event + VECTOR_CLASS synchronizeEvents; + remoteEvent->synchronize(_commandQueue, synchronizeEvents); + nativeEventList.insert(std::end(nativeEventList), + std::begin(synchronizeEvents), std::end(synchronizeEvents)); + } else { // event is a local event + auto eventImpl = std::dynamic_pointer_cast(event); + if (!eventImpl) throw cl::Error(CL_INVALID_EVENT); + nativeEventList.push_back(*eventImpl); + } + } + + _commandQueue.enqueueWaitForEvents(nativeEventList); +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +/* enqueueBarrier is a synchronization point */ +void CommandQueue::enqueueBarrier( + const std::vector> *eventWaitList, + dcl::object_id commandId, std::shared_ptr *event) { + VECTOR_CLASS nativeEventWaitList; + cl::Event barrier; + + /* Obtain wait list of native events */ + if (eventWaitList) { + synchronize(*eventWaitList, nativeEventWaitList); + } + +#if defined(CL_VERSION_1_2) + /* Use native enqueueBarrierWithWaitList */ + _commandQueue.enqueueBarrierWithWaitList( + &nativeEventWaitList, event ? &barrier : nullptr); +#else // #if defined(CL_VERSION_1_2) + /* Use pre-OpenCL 1.2 APIs to implement CommandQueue::enqueueBarrier with wait list */ + /* clEnqueueBarrier (deprecated) does not support an event wait list nor + * does is return an event. */ + if (eventWaitList) { + assert(!"clEnqueueBarrierWithWaitList not implemented"); +#if 0 + try { + /* WARNING: According to the OpenCL 1.1 specification the event list + * of clEnqueueWaitForEvents must not contain user events. Moreover, + * unlike clEnqueueBarrier, clEnqueueWaitForEvents is not explicitly + * defined as a synchronization point. Hence, + * clEnqueueBarrierWithEventList cannot be fully implemented using + * the OpenCL 1.1 APIs. */ + _commandQueue.enqueueWaitForEvents(nativeEventWaitList); + } catch (const cl::Error& err) { + /* cl::CommandQueue::enqueueWaitForEvents throws CL_INVALID_EVENT if + * an event in the wait list is not a valid event, but + * enqueueBarrier (with wait list) must throw + * CL_INVALID_EVENT_WAIT_LIST in this case. */ + if (err.err() == CL_INVALID_EVENT) { + throw cl::Error(CL_INVALID_EVENT_WAIT_LIST); + } else { + throw err; + } + } +#endif + } else { + _commandQueue.enqueueBarrier(); + } + if (event) { + _commandQueue.enqueueMarker(&barrier); + /* Ensure that the marker has finished execution before any future + * command is executed. This is implied for in-order command-queues but + * requires additional synchronization using clEnqueueWaitForEvents for + * out-of-order command-queues. */ + _commandQueue.enqueueWaitForEvents(VECTOR_CLASS(1, barrier)); + /* TODO Lock command-queue when enqueuing clEnqueueBarrierWithWaitList + * No other command must be enqueued concurrently, such that + * clEnqeueueWaitForEvents is executed right after clEnqueueMarker. */ + } +#endif // #if defined(CL_VERSION_1_2) + + /* TODO Implement synchronization for clEnqueueBarrierWithWaitList + * It is not clear from the specification what this means; maybe it acts as + * an active release, i.e. changes to the memory objects by this + * command-queue are replicated to all other compute nodes. */ + + if (event) { // an event should be associated with this command + /* We assume that an event returned by clEnqueueBarrierWithWaitList + * cannot be used to synchronize changes to a memory object across + * command queues, as the specification explicitly stipulates to use + * the event for the command that modified the memory objects for + * synchronization (see Appendix A.1). */ + try { + *event = std::make_shared(commandId, _context, barrier); + } catch (const std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } +} + +const std::shared_ptr& CommandQueue::context() const { + return _context; +} + +} /* namespace dcld */ diff --git a/daemon/src/CommandQueue.h b/daemon/src/CommandQueue.h new file mode 100644 index 0000000..50c80b9 --- /dev/null +++ b/daemon/src/CommandQueue.h @@ -0,0 +1,223 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandQueue.h + * + * \date 2012-08-05 + * \author Philipp Kegel + */ + +#ifndef COMMANDQUEUE_H_ +#define COMMANDQUEUE_H_ + +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcld { + +class Buffer; +class Context; +class Device; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for a native command queue. + * + * This wrapper is required to store the context decorator that should be + * associated with events that are created when enqueuing commands to this + * command queue. + */ +class CommandQueue: public dcl::CommandQueue { +public: + CommandQueue( + const std::shared_ptr& context, + Device * device, + cl_command_queue_properties properties); + virtual ~CommandQueue(); + + /*! + * \brief Returns the native command queue. + */ + operator cl::CommandQueue() const; + + void flush(); + void finish(); + + void enqueueCopyBuffer( + const std::shared_ptr& srcBuffer, + const std::shared_ptr& dstBuffer, + size_t srcOffset, + size_t dstOffset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + void enqueueReadBuffer( + const std::shared_ptr& buffer, + bool blockingRead, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + void enqueueWriteBuffer( + const std::shared_ptr& buffer, + bool blockingWrite, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + void enqueueMapBuffer( + const std::shared_ptr& buffer, + bool blockingMap, + cl_map_flags mapFlags, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + void enqueueUnmapBuffer( + const std::shared_ptr& buffer, + cl_map_flags map_flags, + size_t offset, + size_t size, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + void enqueueNDRangeKernel( + const std::shared_ptr& kernel, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + void enqueueMarker( + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + void enqueueWaitForEvents( + const std::vector>& eventList); +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + + void enqueueBarrier( + const std::vector> *eventWaitList, + dcl::object_id commandId, + std::shared_ptr * event); + + const std::shared_ptr& context() const; + +private: + /* Command queues must be non-copyable */ + CommandQueue( + const CommandQueue& rhs) = delete; + CommandQueue& operator=( + const CommandQueue& rhs) = delete; + + /*! + * \brief Synchronizes this command queue with the events in the event wait list. + * + * If an eventWaitList is found linked to an enqueued command, + * the wait list is searched for events and event listeners. + * Event listener indicate a remote event and could lead into + * an acquire-operation, which is part of the consistency protocol + * + * \param[in] eventWaitList an event wait list + * \param[out] nativeEventWaitList a list of corresponding native events + */ + void synchronize( + const std::vector>& eventWaitList, + VECTOR_CLASS& nativeEventWaitList); + + void enqueueReadBuffer( + const std::shared_ptr& buffer, + bool blocking, + size_t offset, + size_t size, + const VECTOR_CLASS& nativeEventWaitList, + dcl::object_id commandId, + cl::Event& mapData, + cl::Event& unmapData); + + void enqueueWriteBuffer( + const std::shared_ptr& buffer, + bool blocking, + size_t offset, + size_t size, + const VECTOR_CLASS& nativeEventWaitList, + dcl::object_id commandId, + cl::Event& mapData, + cl::Event& unmapData); + + void enqueuePhonyMarker( + bool blocking, + const VECTOR_CLASS& nativeEventWaitList, + dcl::object_id commandId, + cl::Event& marker); + + cl::CommandQueue _commandQueue; //!< Native command queue + + std::shared_ptr _context; //!< Associated context +}; + +} /* namespace dcld */ + +#endif /* COMMANDQUEUE_H_ */ diff --git a/daemon/src/Context.cpp b/daemon/src/Context.cpp new file mode 100644 index 0000000..824a070 --- /dev/null +++ b/daemon/src/Context.cpp @@ -0,0 +1,134 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Context.cpp + * + * \date 2012-03-06 + * \author Philipp Kegel + */ + +#include "Context.h" +#include "Device.h" + +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include + +namespace { + +/*! + * \brief Callback for context error + */ +void onContextError(const char *errinfo, const void *private_info, + size_t cb, void *user_data) { + auto contextListener = static_cast(user_data); + assert(contextListener != nullptr); + contextListener->onError(errinfo, private_info, cb); +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dcld { + +Context::Context( + dcl::Host& host, + const std::vector& computeNodes, + const cl::Platform& platform, + const std::vector& devices, + const std::shared_ptr& listener) : + _host(host), _computeNodes(computeNodes), _listener(listener) { + // if (computeNodes.empty()) { throw cl::Error(CL_INVALID_VALUE); } + if (devices.empty()) { throw cl::Error(CL_INVALID_VALUE); } + + /* TODO Remove self from list of compute nodes */ + + /* TODO Use helper function for device conversion */ + /* convert devices */ + VECTOR_CLASS nativeDevices; + for (auto device : devices) { + auto deviceImpl = dynamic_cast(device); + if (!deviceImpl) throw cl::Error(CL_INVALID_DEVICE); + nativeDevices.push_back(deviceImpl->operator cl::Device()); + } + + /* initialize context properties */ + cl_context_properties properties[] = { + CL_CONTEXT_PLATFORM, + reinterpret_cast(platform()), + 0 /* end of list */ + }; + + _context = cl::Context(nativeDevices, properties, &onContextError, _listener.get()); + _ioCommandQueue = cl::CommandQueue(_context, nativeDevices.front()); +} + +Context::~Context() { } + +Context::operator cl::Context() const { + return _context; +} + +dcl::Host& Context::host() const { + return _host; +} + +const cl::CommandQueue& Context::ioCommandQueue() const { + return _ioCommandQueue; +} + +const std::vector& Context::computeNodes() const { + return _computeNodes; +} + +} /* namespace dcld */ diff --git a/daemon/src/Context.h b/daemon/src/Context.h new file mode 100644 index 0000000..1e6bfec --- /dev/null +++ b/daemon/src/Context.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Context.h + * + * \date 2012-03-06 + * \author Philipp Kegel + */ + +#ifndef CONTEXT_H_ +#define CONTEXT_H_ + +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dcld { + +/*! + * \brief A decorator for a native context. + * + * This wrapper is required to notify context listeners about context errors. + * Moreover, this wrapper holds a command queue for asynchronously reading and + * writing data. + */ +class Context: public dcl::Context { +public: + /* TODO Pass context listener by raw pointer or reference */ + Context( + dcl::Host& host, + const std::vector& computeNodes, + const cl::Platform& platform, + const std::vector& devices, + const std::shared_ptr& listener); + virtual ~Context(); + + operator cl::Context() const; + + dcl::Host& host() const; + const cl::CommandQueue& ioCommandQueue() const; + const std::vector& computeNodes() const; + +private: + /* Contexts must be non-copyable */ + Context( + const Context& rhs) = delete; + Context& operator=( + const Context& rhs) = delete; + + dcl::Host& _host; //!< Host associated with this context + std::vector _computeNodes; //!< Compute nodes associated with this context + + cl::Context _context; //!< Native context + /*! + * \brief Native command queue for asynchronous read/write + * + * This command queue is used to read or write data from any memory object + * that is associated with this context. This is required for the memory + * consistency protocol + */ + cl::CommandQueue _ioCommandQueue; + + std::shared_ptr _listener; +}; + +} /* namespace dcld */ + +#endif /* CONTEXT_H_ */ diff --git a/daemon/src/Device.cpp b/daemon/src/Device.cpp new file mode 100644 index 0000000..d1936e5 --- /dev/null +++ b/daemon/src/Device.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Device.cpp + * + * \date 2013-02-15 + * \author Philipp Kegel + */ + +#include "Device.h" + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dcld { + +Device::Device( + const cl::Device& device) : + _device(device) { +} + +Device::~Device() { +} + +Device::operator cl::Device() const { + return _device; +} + +void Device::getInfo( + cl_device_info param_name, + dcl::Binary& param) const { + size_t param_value_size; + /* Obtain device info using OpenCL C API to avoid unnecessary type + * conversions. */ + cl_int err = ::clGetDeviceInfo(_device(), param_name, 0, nullptr, ¶m_value_size); + if (err == CL_SUCCESS) { + try { + std::unique_ptr param_value(new char[param_value_size]); + err = ::clGetDeviceInfo(_device(), param_name, param_value_size, + param_value.get(), nullptr); + if (err != CL_SUCCESS) throw cl::Error(err); + /* TODO Move pointer into dcl::Binary */ +// param.assign(param_value_size, std::move(param_value)); + param.assign(param_value_size, param_value.get()); + } catch (std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } else { + throw cl::Error(err); + } +} + +} /* namespace dcld */ diff --git a/daemon/src/Device.h b/daemon/src/Device.h new file mode 100644 index 0000000..928ab34 --- /dev/null +++ b/daemon/src/Device.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Device.h + * + * \date 2013-02-15 + * \author Philipp Kegel + */ + +#ifndef DEVICE_H_ +#define DEVICE_H_ + +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dcld { + +class Device: public dcl::Remote, public dcl::Device { +public: + Device( + const cl::Device& device); + virtual ~Device(); + + /*! + * \brief Returns the wrapped OpenCL device. + */ + operator cl::Device() const; + + void getInfo( + cl_device_info param_name, + dcl::Binary& param) const; + + /* TODO Remove dcld::Device::getId */ + dcl::object_id getId() const { return _id; } + /* TODO Remove dcld::Device::getComputeNode */ + dcl::ComputeNode& getComputeNode() const { + throw std::runtime_error("dcl::Device::getComputeNode must not be called on compute node"); + } + +private: + cl::Device _device; +}; + +} /* namespace dcld */ + +#endif /* DEVICE_H_ */ diff --git a/daemon/src/Event.cpp b/daemon/src/Event.cpp new file mode 100644 index 0000000..e553428 --- /dev/null +++ b/daemon/src/Event.cpp @@ -0,0 +1,458 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.cpp + * + * \date 2012-07-28 + * \author Philipp Kegel + */ + +#include "Event.h" + +#include "Context.h" +#include "Memory.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#if 0 +#include +#endif +#include +#include +#include + +namespace { + +#if 0 +/*! + * \brief Generic function to convert OpenCL event callback into a C++-style callback + */ +void eventCallback( + cl_event object_, + cl_int event_command_exec_status, + void *user_data) { + /* convert user data to C++ callback */ + std::unique_ptr> pfn( + static_cast *>(user_data)); + + /* assign event to C++ wrapper */ + cl::Event event; + event() = object_; + cl_int err = ::clRetainEvent(object_); + assert(err == CL_SUCCESS); + + (*pfn)(event, event_command_exec_status); // execute callback +} +#endif + +/*! + * \brief Callback for updating an event status + */ +void onEventComplete(cl_event object_, cl_int execution_status, + void *user_data) { + auto event = static_cast(user_data); + assert(execution_status == CL_COMPLETE || execution_status < 0); + // FIXME Event::operator() fails, if host process has been killed during data transfer + assert(event != nullptr && event->operator cl::Event()() == object_); + event->onExecutionStatusChanged(execution_status); +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dcld { + +Event::Event( + const std::shared_ptr& context, + const std::vector>& memoryObjects) : + _context(context), _memoryObjects(memoryObjects) { + /* do not check context here, to allow for error handling in derived classes */ +} + +Event::Event( + const std::shared_ptr& context, + const std::shared_ptr& memoryObject) : + _context(context), _memoryObjects(1, memoryObject) { } + +Event::Event( + const std::shared_ptr& context) : + _context(context) { } + +/* ****************************************************************************/ + +RemoteEvent::RemoteEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects) : + dcl::Remote(id), Event(context, memoryObjects) { + if (!context) throw cl::Error(CL_INVALID_CONTEXT); + + _event = cl::UserEvent(*_context); +} + +RemoteEvent::operator cl::Event() const { + return _event; +} + +void RemoteEvent::synchronize( + const cl::CommandQueue& commandQueue, + VECTOR_CLASS& nativeEventList) { + std::lock_guard lock(_syncMutex); + + dcl::util::Logger << dcl::util::Debug + << "Synchronizing replacement event with remote event (ID=" << _id << ')' + << std::endl; + + if ( !_memoryObjects.empty() /* synchronization of memory objects required */ + && _syncEvents.empty() /* no synchronization performed yet */) { + /* + * Trigger event synchronization on host + */ + /* TODO Use SychronizationListener interface to send message */ + /* TODO Send message to event owner (host or compute node) */ + dclasio::message::EventSynchronizationMessage msg(_id); + _context->host().sendMessage(msg); + dcl::util::Logger << dcl::util::Debug + << "Sent event synchronization message to host (ID=" << _id << ')' + << std::endl; + + for (auto memoryObject : _memoryObjects) { + cl::Event acquire; /* Event representing the acquire operation of the current memory object. + * Serves as synchronization point for following commands and other devices */ + memoryObject->acquire(_context->host(), commandQueue, _event, &acquire); + _syncEvents.push_back(acquire); + } + } + + nativeEventList = _syncEvents; +} + +void RemoteEvent::getProfilingInfo(cl_profiling_info param_name, + cl_ulong& param_value) const { + /* Remote events rely on a user event and thus cannot provide profiling + * info. This info can only be obtained from the native event this event + * is associated with, i.e. listening to. */ + throw cl::Error(CL_PROFILING_INFO_NOT_AVAILABLE); +} + +void RemoteEvent::onExecutionStatusChanged(cl_int executionStatus) { + assert(executionStatus == CL_COMPLETE || executionStatus < 0); + _event.setStatus(executionStatus); +} + +void RemoteEvent::onSynchronize(dcl::Process& process) { + dcl::util::Logger << dcl::util::Error + << "Synchronization attempt on replacement event (ID=" << _id << ')' + << std::endl; +} + +/* ****************************************************************************/ + +LocalEvent::LocalEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects) : + dcl::Remote(id), Event(context, memoryObjects), + _received(dcl::util::clock.getTime()) { + /* local events are created by command queue methods, which should pass checked arguments */ + assert(context != nullptr && "Invalid context"); +} + +LocalEvent::LocalEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject) : + dcl::Remote(id), Event(context, memoryObject), + _received(dcl::util::clock.getTime()) { + /* local events are created by command queue methods, which should pass checked arguments */ + assert(context != nullptr && "Invalid context"); +} + +LocalEvent::LocalEvent(dcl::object_id id, + const std::shared_ptr& context) : + dcl::Remote(id), Event(context), + _received(dcl::util::clock.getTime()) { + /* local events are created by command queue methods, which should pass checked arguments */ + assert(context != nullptr && "Invalid context"); +} + +LocalEvent::~LocalEvent() { +} + +void LocalEvent::onSynchronize(dcl::Process& process) { + cl::CommandQueue commandQueue = _context->ioCommandQueue(); + + dcl::util::Logger << dcl::util::Debug + << "Event synchronization (ID=" << _id + << ") requested by '" << process.url() << '\'' + << std::endl; + + /* Acquire changes to memory objects associated with this event. + * The acquire operations are performed using the context's I/O command + * queue. This queue is reserved for synchronization and thus does not + * interfere (e.g., deadlock) with application commands. */ + for (auto memoryObject : _memoryObjects) { + memoryObject->release(process, commandQueue, *this); + } + + /* The I/O command queue must be flushed to ensure instant execution of the + * acquire operation */ + commandQueue.flush(); +} + +/* ****************************************************************************/ + +SimpleEvent::SimpleEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects, + const cl::Event& event) : + LocalEvent(id, context, memoryObjects), _event(event) +{ + /* Schedule event status update notification */ + _event.setCallback(CL_COMPLETE, &onEventComplete, this); +} + +SimpleEvent::SimpleEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject, + const cl::Event& event) : + LocalEvent(id, context, memoryObject), _event(event) +{ + /* Schedule event status update notification */ + _event.setCallback(CL_COMPLETE, &onEventComplete, this); +} + +SimpleEvent::SimpleEvent(dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& event) : + LocalEvent(id, context), _event(event) +{ + /* Schedule event status update notification */ + _event.setCallback(CL_COMPLETE, &onEventComplete, this); +} + +SimpleEvent::operator cl::Event() const { + return _event; +} + +void SimpleEvent::getProfilingInfo(cl_profiling_info param_name, + cl_ulong& param_value) const { + switch (param_name) { + case CL_PROFILING_COMMAND_RECEIVED_WWU: + param_value = _received; + break; + default: + _event.getProfilingInfo(param_name, ¶m_value); + /* no break */ + } +} + +void SimpleEvent::onExecutionStatusChanged(cl_int executionStatus) { + dclasio::message::CommandExecutionStatusChangedMessage message(_id, executionStatus); + + try { + /* Broadcast execution status to remote events */ + _context->host().sendMessage(message); + sendMessage(_context->computeNodes(), message); + + dcl::util::Logger << dcl::util::Debug + << "Sent update of command execution status (ID=" << _id + << ", status=" << executionStatus << ')' + << std::endl; + } catch (const dcl::IOException& err) { + dcl::util::Logger << dcl::util::Error + << "Sending update of command execution status failed (ID=" << _id + << ", status=" << executionStatus << ')' + << std::endl; + } +} + +/* ****************************************************************************/ + +SimpleNodeEvent::SimpleNodeEvent(dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& event) : + SimpleEvent(id, context, event) { } + +void SimpleNodeEvent::onExecutionStatusChanged(cl_int executionStatus) { + if (!_context->computeNodes().empty()) { + dclasio::message::CommandExecutionStatusChangedMessage message(_id, executionStatus); + + try { + /* Broadcast execution status to remote on other compute nodes. + * No message has to be sent to the host. */ + sendMessage(_context->computeNodes(), message); + + dcl::util::Logger << dcl::util::Debug + << "Sent update of command execution status to compute nodes (ID=" << _id + << ", status=" << executionStatus << ')' + << std::endl; + } catch (const dcl::IOException& err) { + dcl::util::Logger << dcl::util::Error + << "Sending update of command execution status to compute nodes failed (ID=" << _id + << ", status=" << executionStatus << ')' + << std::endl; + } + } +} + +/* ****************************************************************************/ + +CompoundEvent::CompoundEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject, + const cl::Event& startEvent, + const cl::Event& endEvent) : + LocalEvent(id, context, memoryObject), _startEvent(startEvent), + _endEvent(endEvent) { } + +CompoundEvent::CompoundEvent(dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& startEvent, + const cl::Event& endEvent) : + LocalEvent(id, context), _startEvent(startEvent), _endEvent(endEvent) { } + +CompoundEvent::operator cl::Event() const { + return _endEvent; +} + +void CompoundEvent::getProfilingInfo(cl_profiling_info param_name, + cl_ulong& param_value) const { + switch (param_name) { + case CL_PROFILING_COMMAND_RECEIVED_WWU: + param_value = _received; + break; + case CL_PROFILING_COMMAND_QUEUED: + /* no break */ + case CL_PROFILING_COMMAND_SUBMIT: + /* no break */ + case CL_PROFILING_COMMAND_START: + _startEvent.getProfilingInfo(param_name, ¶m_value); + break; + case CL_PROFILING_COMMAND_END: + _endEvent.getProfilingInfo(param_name, ¶m_value); + break; + default: + throw cl::Error(CL_INVALID_VALUE); + /* no break */ + } +} + +/* ****************************************************************************/ + +ReadMemoryEvent::ReadMemoryEvent(dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& startEvent, + const cl::Event& endEvent) : + CompoundEvent(id, context, startEvent, endEvent) { } + +void ReadMemoryEvent::getProfilingInfo( + cl_profiling_info param_name, + cl_ulong& param_value) const { + switch (param_name) { + case CL_PROFILING_COMMAND_END: + /* A read event is finished on the host when data receipt is complete. + * In some cases, the receipt on the host may be complete while the + * unmap operation on the daemon (associated with _endEvent) is not, + * such that the profiling info for that event is not available yet. + * Waiting for this event ensures that the unmap is complete before the + * profiling info is obtained. */ + /* FIXME Waiting for an event must be timed to avoid deadlocks */ + _endEvent.wait(); + break; + } + + CompoundEvent::getProfilingInfo(param_name, param_value); +} + +void ReadMemoryEvent::onExecutionStatusChanged(cl_int executionStatus) { + /* Do nothing - the read operation is finished by the host */ +} + +/* ****************************************************************************/ + +WriteMemoryEvent::WriteMemoryEvent(dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject, + const cl::Event& startEvent, + const cl::Event& endEvent) : + CompoundEvent(id, context, memoryObject, startEvent, endEvent) { + /* Schedule event status update notification */ + _endEvent.setCallback(CL_COMPLETE, &onEventComplete, this); +} + +void WriteMemoryEvent::onExecutionStatusChanged(cl_int executionStatus) { + if (!_context->computeNodes().empty()) { + dclasio::message::CommandExecutionStatusChangedMessage message(_id, executionStatus); + + try { + /* Broadcast execution status to remote on other compute nodes. + * No message has to be sent to the host. */ + sendMessage(_context->computeNodes(), message); + + dcl::util::Logger << dcl::util::Debug + << "Sent update of command execution status to compute nodes (ID=" << _id + << ", status=" << executionStatus << ')' + << std::endl; + } catch (const dcl::IOException& err) { + dcl::util::Logger << dcl::util::Error + << "Sending update of command execution status to compute nodes failed (ID=" << _id + << ", status=" << executionStatus << ')' + << std::endl; + } + } +} + +} /* namespace dcld */ diff --git a/daemon/src/Event.h b/daemon/src/Event.h new file mode 100644 index 0000000..670cb32 --- /dev/null +++ b/daemon/src/Event.h @@ -0,0 +1,389 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.h + * + * \date 2012-07-28 + * \author Philipp Kegel + * \author Sebastian Pribnow + */ + +#ifndef EVENT_H_ +#define EVENT_H_ + +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcld { + +class Context; +class Memory; + +/* ****************************************************************************/ + +/*! + * \brief An abstract base class for a decorator for any kind of event. + * + * This wrapper associates a native event (not part of this class, hence it is + * abstract) with a context and a list of memory objects. + */ +class Event: public dcl::Event { +public: + Event( + const std::shared_ptr& context, + const std::vector>& memoryObjects); + Event( + const std::shared_ptr& context, + const std::shared_ptr& memoryObject); + Event( + const std::shared_ptr& context); + + /*! + * \brief Returns the native event associated with this decorator + */ + virtual operator cl::Event() const = 0; + +protected: + std::shared_ptr _context; //!< Context associated with this event + /*! + * \brief Memory objects associated with this event's command + * + * The memory objects in this list are synchronized when the command + * associated with this event is complete, and when this event is passed to + * a command in an event wait list. + */ + std::vector> _memoryObjects; + +private: + /* Events must be non-copyable */ + Event( + const Event& rhs) = delete; + Event& operator=( + const Event& rhs) = delete; +}; + +/* ****************************************************************************/ + +/*! + * \brief A replacement for an event on another compute node or on the host. + * + * A remote event is a substitute event for a native event on another compute + * node or host (i.e., a user event). Internally, a native user event is provided + * and passed to native OpenCL functions as a replacement. + */ +class RemoteEvent: public dcl::Remote, public Event { +public: + RemoteEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects); + + operator cl::Event() const; + + /*! + * \brief Synchronizes (acquires) the changes associated with the remote event + * + * \param[in] commandQueue the command queue used for acquiring changes + * \param[in] nativeEventList the native events associated with the acquiring operations + */ + void synchronize( + const cl::CommandQueue& commandQueue, + VECTOR_CLASS& nativeEventList); + + /* + * Event API + */ + void getProfilingInfo( + cl_profiling_info param_name, + cl_ulong& param_value) const; + + /* + * Command listener API + */ + + void onExecutionStatusChanged( + cl_int executionStatus); + + /* + * Synchronization listener API + */ + + void onSynchronize( + dcl::Process& process); + +private: + cl::UserEvent _event; //!< Native user event + std::vector _syncEvents; //!< Native events used for synchronization + mutable std::mutex _syncMutex; //!< Mutex for synchronization event list +}; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for one or more native events that are associated with a command. + * + * The method onExecutionStatusChanged (inherited from CommandListener) is + * called by wrapped events, i.e., locally, rather than by messages from other + * processes. + */ +class LocalEvent: public dcl::Remote, public Event { +public: + /*! + * \brief Wraps a native OpenCL event on this compute node. + */ + LocalEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects); + LocalEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject); + LocalEvent( + dcl::object_id id, + const std::shared_ptr& context); + + ~LocalEvent(); + + /* + * Synchronization listener API + */ + + void onSynchronize( + dcl::Process& process); + +protected: + cl_ulong _received; //!< Receipt time of associated command +}; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for a single native event. + * + * This is a basic implementation of the LocalEvent class. It forwards API + * calls to its native events and broadcasts a 'command complete' message when + * the command associated with this event is completed or terminated. + */ +class SimpleEvent: public LocalEvent { +public: + /*! + * \brief Creates an event by decorating a native OpenCL event. + */ + SimpleEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects, + const cl::Event& event); + SimpleEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject, + const cl::Event& event); + SimpleEvent( + dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& event); + + operator cl::Event() const; + + /* + * Event API + */ + + void getProfilingInfo( + cl_profiling_info param_name, + cl_ulong& param_value) const; + + /* + * Command listener API + */ + + void onExecutionStatusChanged( + cl_int executionStatus); + +private: + cl::Event _event; //!< Native event +}; + +/* ****************************************************************************/ + +/*! + * This is an implementation of the SimpleEvent class which sends a 'command + * complete' message to other compute nodes, but *not* to the host. This message + * is sent to the host by the mechanism that implements the associated command, + * while this event is only responsible for sending the message to other compute + * nodes. + */ +class SimpleNodeEvent: public SimpleEvent { +public: + /*! + * \brief Creates an event by decorating a native OpenCL event. + */ + SimpleNodeEvent( + dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& event); + + /* + * Command listener API + */ + + void onExecutionStatusChanged( + cl_int executionStatus); +}; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for the native events of a number associated commands. + * + * This abstract class is an implementation of LocalEvent which depends on two + * native events. Its provides a native event which is used by a native OpenCL + * implementation as a replacement for itself and obtains profiling information + * by merging information from its two native events. + */ +class CompoundEvent: public LocalEvent { +public: + /*! + * \brief Creates a compound event from two native OpenCL events. + */ + CompoundEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject, + const cl::Event& startEvent, + const cl::Event& endEvent); + CompoundEvent( + dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& startEvent, + const cl::Event& endEvent); + + operator cl::Event() const; + + /* + * Event API + */ + + void getProfilingInfo( + cl_profiling_info param_name, + cl_ulong& param_value) const; + +protected: + cl::Event _startEvent; //!< Native event associated with the start of this compound event + cl::Event _endEvent; //!< Native event associated with the completion of this compound event +}; + +/* ****************************************************************************/ + +/*! + * \brief A compound event associated with a read buffer or read image command. + * + * This class is an implementation of CompoundEvent which sends no 'command + * complete' messages, as this message is send by the host for read buffer/image + * commands. + */ +class ReadMemoryEvent: public CompoundEvent { +public: + ReadMemoryEvent( + dcl::object_id id, + const std::shared_ptr& context, + const cl::Event& startEvent, + const cl::Event& endEvent); + + /* + * Event API + */ + + void getProfilingInfo( + cl_profiling_info param_name, + cl_ulong& param_value) const; + + /* + * Command listener API + */ + + void onExecutionStatusChanged( + cl_int executionStatus); +}; + +/* ****************************************************************************/ + +/*! + * \brief A compound event associated with a write buffer or write image command. + * + * This is an implementation of the CompoundEvent class which sends a 'command + * complete' message to other compute nodes, but *not* to the host. This message + * is sent to the host by the mechanism that implements the 'write memory + * object' command while this event is only responsible for sending the message + * to other compute nodes. + */ +class WriteMemoryEvent: public CompoundEvent { +public: + WriteMemoryEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::shared_ptr& memoryObject, + const cl::Event& startEvent, + const cl::Event& endEvent); + + /* + * Command listener API + */ + + void onExecutionStatusChanged( + cl_int executionStatus); +}; + +} /* namespace dcld */ + +#endif /* EVENT_H_ */ diff --git a/daemon/src/Kernel.cpp b/daemon/src/Kernel.cpp new file mode 100644 index 0000000..58b2cfd --- /dev/null +++ b/daemon/src/Kernel.cpp @@ -0,0 +1,188 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Kernel.cpp + * + * @date 2011-12-09 + * @author Philipp Kegel + */ + +#include "Kernel.h" + +#include "Device.h" +#include "Memory.h" +#include "Program.h" + +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +namespace dcld { + +Kernel::Kernel(const std::shared_ptr& program, const char *name) { + if (!program) throw cl::Error(CL_INVALID_PROGRAM); + + _kernel = cl::Kernel(*program, name); + _writeMemoryObjects.resize(_kernel.getInfo()); +} + +Kernel::Kernel(const cl::Kernel& kernel) : _kernel(kernel) { } + +Kernel::~Kernel() { } + +Kernel::operator cl::Kernel() const { + return _kernel; +} + +void Kernel::getInfo( + cl_kernel_info param_name, + dcl::Binary& param) const { + size_t param_value_size; + /* Obtain kernel info using OpenCL C API to avoid unnecessary type + * conversions. */ + cl_int err = ::clGetKernelInfo(_kernel(), param_name, 0, nullptr, ¶m_value_size); + if (err == CL_SUCCESS) { + try { + std::unique_ptr param_value(new char[param_value_size]); + err = ::clGetKernelInfo(_kernel(), + param_name, + param_value_size, param_value.get(), + nullptr); + if (err != CL_SUCCESS) throw cl::Error(err); + /* TODO Move pointer into dcl::Binary */ +// param.assign(param_value_size, std::move(param_value)); + param.assign(param_value_size, param_value.get()); + } catch (std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } else { + throw cl::Error(err); + } +} + +void Kernel::getWorkGroupInfo( + const dcl::Device *device, + cl_kernel_work_group_info param_name, + dcl::Binary& param) const { + auto deviceImpl = dynamic_cast(device); + if (!deviceImpl) throw cl::Error(CL_INVALID_DEVICE); + + size_t param_value_size; + /* Obtain kernel work group info using OpenCL C API to avoid unnecessary + * type conversions. */ + cl_int err = ::clGetKernelWorkGroupInfo( + _kernel(), deviceImpl->operator cl::Device()(), param_name, 0, nullptr, ¶m_value_size); + if (err == CL_SUCCESS) { + try { + std::unique_ptr param_value(new char[param_value_size]); + err = ::clGetKernelWorkGroupInfo( + _kernel(), + deviceImpl->operator cl::Device()(), + param_name, + param_value_size, param_value.get(), + nullptr); + if (err != CL_SUCCESS) throw cl::Error(err); + /* TODO Move pointer into dcl::Binary */ +// param.assign(param_value_size, std::move(param_value)); + param.assign(param_value_size, param_value.get()); + } catch (std::bad_alloc&) { + throw cl::Error(CL_OUT_OF_RESOURCES); + } + } else { + throw cl::Error(err); + } +} + +void Kernel::setArg(cl_uint index, + const std::shared_ptr& memory) { + auto memoryImpl = std::dynamic_pointer_cast(memory); + if (!memoryImpl) throw cl::Error(CL_INVALID_MEM_OBJECT); + + _kernel.setArg(index, memoryImpl->operator cl::Memory()()); + + if (memoryImpl->isOutput()) { // memory object will be modified by kernel + /* If a writable (CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE) + * memory object is set as kernel argument, it is assumed + * that the kernel will modify this memory object. */ + assert(index < _writeMemoryObjects.size()); + if (_writeMemoryObjects.size() <= index) { + _writeMemoryObjects.resize(index + 1); + } + _writeMemoryObjects[index] = memoryImpl; + } +} + +void Kernel::setArg(cl_uint index, const cl::Sampler& sampler) { + _kernel.setArg(index, sampler); +} + +void Kernel::setArg(cl_uint index, size_t size, const void *argPtr) { + /* Const-ness has to be stripped from the argument value, as the OpenCL C++ + * binding requires a non-const argument value. Though, this argument is + * directly passed to the C API which argument is const. */ + _kernel.setArg(index, size, const_cast(argPtr)); +} + +std::vector> Kernel::writeMemoryObjects() { + std::set> writeMemoryObjects; + + /* copy memory objects from argument list to set to remove duplicates */ + for (auto memoryObject : _writeMemoryObjects) { + /* ignore empty (NULL) entries */ + if (memoryObject) writeMemoryObjects.insert(memoryObject); + } + + /* return value optimization should kick-in here to avoid copying */ + return std::vector>(std::begin(writeMemoryObjects), + std::end(writeMemoryObjects)); +} + +} /* namespace dcld */ diff --git a/daemon/src/Kernel.h b/daemon/src/Kernel.h new file mode 100644 index 0000000..23e6662 --- /dev/null +++ b/daemon/src/Kernel.h @@ -0,0 +1,130 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Kernel.h + * + * \date 2011-12-09 + * \author Philipp Kegel + */ + +#ifndef KERNEL_H_ +#define KERNEL_H_ + +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcld { + +class Memory; +class Program; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for a native kernel. + * + * This wrapper is required to store memory objects which are passed to a + * kernel as arguments. + */ +class Kernel: public dcl::Kernel { +public: + Kernel( + const std::shared_ptr& program, + const char * name); + Kernel( + const cl::Kernel& kernel); + virtual ~Kernel(); + + /*! + * \brief Returns the wrapped OpenCL kernel. + */ + operator cl::Kernel() const; + + void getInfo( + cl_kernel_info param_name, + dcl::Binary& param) const; + void getWorkGroupInfo( + const dcl::Device * device, + cl_kernel_work_group_info param_name, + dcl::Binary& param) const; + + void setArg( + cl_uint index, + const std::shared_ptr& memoryObject); + void setArg( + cl_uint index, + const cl::Sampler& sampler); + void setArg( + cl_uint index, + size_t size, + const void *argPtr = nullptr); + + /*! + * \brief Returns the memory objects (possibly) written to with this kernel + * + * \return a list of memory objects + */ + std::vector> writeMemoryObjects(); + +private: + /* Kernels must be non-copyable */ + Kernel( + const Kernel& rhs) = delete; + Kernel& operator=( + const Kernel& rhs) = delete; + + cl::Kernel _kernel; //!< Native kernel + + std::vector> _writeMemoryObjects; //!< Memory objects used by this kernel +}; + +} /* namespace dcld */ + +#endif /* KERNEL_H_ */ diff --git a/daemon/src/Memory.cpp b/daemon/src/Memory.cpp new file mode 100644 index 0000000..05ee38c --- /dev/null +++ b/daemon/src/Memory.cpp @@ -0,0 +1,294 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Memory.cpp + * + * \date 2011-09-01 + * \author Philipp Kegel + */ + +#include "Memory.h" + +#include "Context.h" + +#include +#include +#include + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include + +namespace { + +struct ExecData { + dcl::Process *process; + size_t size; + void *ptr; + cl::UserEvent event; +}; + +void execAcquire(cl_event event, cl_int execution_status, void *user_data) { + std::unique_ptr syncData(static_cast(user_data)); + + assert(execution_status == CL_COMPLETE || execution_status < 0); + assert(syncData != nullptr); + + if (execution_status == CL_COMPLETE) { + dcl::util::Logger << dcl::util::Debug + << "(SYN) Acquiring memory object data from process '" + << syncData->process->url() << '\'' + << std::endl; + + try { + auto recv = syncData->process->receiveData(syncData->size, syncData->ptr); + recv->setCallback( + std::bind(&cl::UserEvent::setStatus, syncData->event, std::placeholders::_1)); + } catch (const dcl::IOException& e) { + dcl::util::Logger << dcl::util::Error + << "Data receipt failed: " << e.what() << std::endl; + syncData->event.setStatus(CL_IO_ERROR_WWU); + } + } else { + dcl::util::Logger << dcl::util::Error + << "(SYN) Acquiring memory object data failed" + << std::endl; + + syncData->event.setStatus(execution_status); + } +} + +void execRelease(cl_event event, cl_int execution_status, void *user_data) { + std::unique_ptr syncData(static_cast(user_data)); + + assert(execution_status == CL_COMPLETE || execution_status < 0); + assert(syncData != nullptr); + + if (execution_status == CL_COMPLETE) { + dcl::util::Logger << dcl::util::Debug + << "(SYN) Releasing memory object data to process '" + << syncData->process->url() << '\'' + << std::endl; + + try { + auto send = syncData->process->sendData(syncData->size, syncData->ptr); + send->setCallback( + std::bind(&cl::UserEvent::setStatus, syncData->event, std::placeholders::_1)); + } catch (const dcl::IOException& e) { + dcl::util::Logger << dcl::util::Error + << "Data sending failed: " << e.what() << std::endl; + syncData->event.setStatus(CL_IO_ERROR_WWU); + } + } else { + dcl::util::Logger << dcl::util::Error + << "(SYN) Releasing memory object data failed" + << std::endl; + + syncData->event.setStatus(execution_status); + } +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dcld { + +/* **************************************************************************** + * Memory object + ******************************************************************************/ + +Memory::Memory(const std::shared_ptr& context) : + _context(context) { +} + +Memory::~Memory() { } + +size_t Memory::size() const { + return static_cast(*this).getInfo(); +} + +bool Memory::isInput() const{ + return (static_cast(*this).getInfo() & + (CL_MEM_READ_ONLY | CL_MEM_READ_WRITE)); +} + +bool Memory::isOutput() const { + return (static_cast(*this).getInfo() & + (CL_MEM_WRITE_ONLY | CL_MEM_READ_WRITE)); +} + +/* **************************************************************************** + * Buffer + ******************************************************************************/ + +Buffer::Buffer( + const std::shared_ptr& context, cl_mem_flags flags, + size_t size, void *ptr) : + dcld::Memory(context) +{ + cl_mem_flags rwFlags = flags & + (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY); +// cl_mem_flags hostPtrFlags = flags & +// (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR); + cl_mem_flags allocHostPtr = flags & + CL_MEM_ALLOC_HOST_PTR; + + /* + * Always let the OpenCL implementation allocate the memory on the compute + * node to ensure optimal performance. + * If CL_MEM_USE_HOST_PTR is specified, the compute node should try to use + * pinned memory to ensure optimal performance for frequent data transfers. + */ + + if (ptr) { + /* TODO Improve data transfer on buffer creation + * Use map/unmap to avoid explicit memory allocation *or* + * copy data only on host */ + _buffer = cl::Buffer(*_context, rwFlags | CL_MEM_COPY_HOST_PTR | allocHostPtr, size, ptr); + } else { + /* create uninitialized buffer */ + _buffer = cl::Buffer(*_context, rwFlags | allocHostPtr, size); + } +} + +Buffer::~Buffer() { } + +Buffer::operator cl::Memory() const { + return _buffer; +} + +Buffer::operator cl::Buffer() const { + return _buffer; +} + +void Buffer::acquire( + dcl::Process& process, + const cl::CommandQueue& commandQueue, + const cl::Event& releaseEvent, + cl::Event *acquireEvent) { + cl::Event mapEvent; + cl::UserEvent dataReceipt(*_context); + + dcl::util::Logger << dcl::util::Debug + << "(SYN) Acquiring buffer from process '" << process.url() << '\'' + << std::endl; + + /* map buffer to host memory when releaseEvent is complete */ + VECTOR_CLASS mapWaitList(1, releaseEvent); + void *ptr = commandQueue.enqueueMapBuffer( + _buffer, + CL_FALSE, + CL_MAP_WRITE, + 0, size(), + &mapWaitList, &mapEvent); + + auto syncData = new ExecData; + syncData->process = &process; + syncData->size = size(); + syncData->ptr = ptr; + syncData->event = dataReceipt; + + /* receive buffer data when mapping is complete */ + mapEvent.setCallback(CL_COMPLETE, &execAcquire, syncData); + + /* WARNING: do not use syncData after this point, as the callback of + * mapEvent deletes it concurrently */ + + /* unmap buffer when acquire operation is complete */ + VECTOR_CLASS unmapWaitList(1, dataReceipt); + commandQueue.enqueueUnmapMemObject( + _buffer, + ptr, + &unmapWaitList, acquireEvent); +} + +void Buffer::release( + dcl::Process& process, + const cl::CommandQueue& commandQueue, + const cl::Event& releaseEvent) const { + cl::Event mapEvent; + cl::UserEvent dataSending(*_context); + + dcl::util::Logger << dcl::util::Debug + << "(SYN) Releasing buffer to process '" << process.url() << '\'' + << std::endl; + + /* map buffer when releaseEvent is complete */ + VECTOR_CLASS mapWaitList(1, releaseEvent); + void *ptr = commandQueue.enqueueMapBuffer( + _buffer, + CL_FALSE, + CL_MAP_READ, + 0, size(), + &mapWaitList, &mapEvent + ); + + auto syncData = new ExecData; + syncData->process = &process; + syncData->size = size(); + syncData->ptr = ptr; + syncData->event = dataSending; + + /* send buffer data when mapping is complete */ + mapEvent.setCallback(CL_COMPLETE, &execRelease, syncData); + + /* WARNING: do not use syncData after this point, as the callback of + * mapEvent deletes it concurrently */ + + /* unmap buffer when acquire operation is complete */ + VECTOR_CLASS unmapWaitList(1, dataSending); + commandQueue.enqueueUnmapMemObject( + _buffer, + ptr, + &unmapWaitList, nullptr); +} + +} /* namespace dcld */ diff --git a/daemon/src/Memory.h b/daemon/src/Memory.h new file mode 100644 index 0000000..92056bb --- /dev/null +++ b/daemon/src/Memory.h @@ -0,0 +1,178 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Memory.h + * + * \date 2011-09-01 + * \author Philipp Kegel + */ + +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dcld { + +class Context; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for a native memory object. + * + * This wrapper is used to implement memory consistency across nodes in dOpenCL. + */ +class Memory: public virtual dcl::Memory { +public: + virtual ~Memory(); + + virtual operator cl::Memory() const = 0; + + size_t size() const; + + /*! + * \brief Checks is this memory is used as input. + * + * isOutput and isInput are NOT mutually exclusive. + * + * \return \c true, if this memory is used as input, otherwise \c false. + * \see isOutput + */ + bool isInput() const; + + /*! + * \brief Checks is this memory is used as output. + * + * isOutput and isInput are NOT mutually exclusive. + * + * \return \c true, if this memory is used as output, otherwise \c false. + * \see isInput + */ + bool isOutput() const; + + /*! + * \brief Acquires the changes to this memory object associated with \c releaseEvent + * + * \param[in] process the process from which the changes should be acquired + * \param[in] commandQueue command queue for uploading the received data + * \param[in] releaseEvent event that releases the changes to be acquired + * \param[out] acquireEvent event associated with this acquire operation + */ + virtual void acquire( + dcl::Process& process, + const cl::CommandQueue& commandQueue, + const cl::Event& releaseEvent, + cl::Event * acquireEvent) = 0; + + /*! + * \brief Releases the changes to this memory object associated with \c releaseEvent + * + * The updated data of this memory object are sent to the requesting \c process. + * \c commandQueue is used to obtain the data from the local OpenCL implementation. + * + * \param[in] process the process that requested the acquire operation + * \param[in] commandQueue command queue for downloading data before + * sending + * \param[in] releaseEvent event associated with the operation that + * releases the changes to be acquired + */ + virtual void release( + dcl::Process& process, + const cl::CommandQueue& commandQueue, + const cl::Event& releaseEvent) const = 0; + +protected: + Memory( + const std::shared_ptr& context); + + /* Memory objects must be non-copyable */ + Memory( + const Memory& rhs) = delete; + Memory& operator=( + const Memory&) = delete; + + std::shared_ptr _context; //!< Context associated with this memory object +}; + +/* ****************************************************************************/ + +class Buffer: public dcl::Buffer, public Memory { +public: + /*! + * \brief Creates an uninitialized buffer. + */ + Buffer( + const std::shared_ptr& context, + cl_mem_flags flags, + size_t size, + void * ptr); + virtual ~Buffer(); + + operator cl::Memory() const; + operator cl::Buffer() const; + + void acquire( + dcl::Process& process, + const cl::CommandQueue& commandQueue, + const cl::Event& releaseEvent, + cl::Event * acquireEvent); + + void release( + dcl::Process& process, + const cl::CommandQueue& commandQueue, + const cl::Event& releaseEvent) const; + +private: + cl::Buffer _buffer; //!< Native buffer +}; + +} /* namespace dcld */ + +#endif /* MEMORY_H_ */ diff --git a/daemon/src/Program.cpp b/daemon/src/Program.cpp new file mode 100644 index 0000000..0fdaa34 --- /dev/null +++ b/daemon/src/Program.cpp @@ -0,0 +1,217 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Program.cpp + * + * \date 2012-07-30 + * \author Philipp Kegel + */ + +#include "Program.h" + +#include "Context.h" +#include "Device.h" +#include "Kernel.h" + +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +#if USE_PROGRAM_BUILD_LISTENER +namespace dcld { + +namespace detail { + +class ProgramBuild { +public: + ProgramBuild( + Program& program, + const std::vector& devices, + const std::shared_ptr& listener) : + _program(program), _devices(devices), _listener(listener) { } + virtual ~ProgramBuild() { } + + void onComplete() { + std::vector buildStatus; + + /* Query program build status */ + buildStatus.reserve(_devices.size()); + for (auto device : _devices) { + auto deviceImpl = dynamic_cast(device); + /* Device has been checked in dcld::Program::build */ + assert(deviceImpl != nullptr); + buildStatus.push_back( + static_cast(_program).getBuildInfo(*deviceImpl)); + } + + _listener->onComplete(_devices, buildStatus); + } + +private: + Program& _program; + std::vector _devices; + std::shared_ptr _listener; +}; + +} /* namespace detail */ + +} /* namespace dcld */ + +/* ****************************************************************************/ + +namespace { + +/*! + * \brief Callback for completion of program build + */ +void onProgramBuildComplete(cl_program object_, void *user_data) { + std::unique_ptr programBuild( + static_cast(user_data)); + assert(programBuild != nullptr); + programBuild->onComplete(); +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ +#endif + +namespace dcld { + +Program::Program(const std::shared_ptr& context, + const char *source, size_t length) : + _context(context) +{ + if (!context) throw cl::Error(CL_INVALID_CONTEXT); + + cl::Program::Sources sources; + sources.push_back(std::make_pair(source, length)); + + /* Create native program */ + _program = cl::Program(*_context, sources); +} + +Program::Program( + const std::shared_ptr& context, + const std::vector& devices, + const std::vector& lengths, + const unsigned char **binaries, + VECTOR_CLASS *binary_status) : + _context(context) +{ + if (!context) throw cl::Error(CL_INVALID_CONTEXT); + + /* TODO Initialize program binaries */ + cl::Program::Binaries binaries_; + assert(!"Program creation with binaries not implemented"); + + /* TODO Use helper function for device conversion */ + /* convert devices */ + VECTOR_CLASS nativeDevices; + for (auto device : devices) { + auto deviceImpl = dynamic_cast(device); + if (!deviceImpl) throw cl::Error(CL_INVALID_DEVICE); + nativeDevices.push_back(deviceImpl->operator cl::Device()); + } + + /* Create native program */ + _program = cl::Program(*context, nativeDevices, binaries_, binary_status); +} + +Program::~Program() { } + +Program::operator cl::Program() const { + return _program; +} + +void Program::build( + const std::vector& devices, + const char *options, + const std::shared_ptr& programBuildListener) { + /* TODO Use helper function for device conversion */ + /* convert devices */ + VECTOR_CLASS nativeDevices; + for (auto device : devices) { + auto deviceImpl = dynamic_cast(device); + if (!deviceImpl) throw cl::Error(CL_INVALID_DEVICE); + nativeDevices.push_back(deviceImpl->operator cl::Device()); + } + +#if USE_PROGRAM_BUILD_LISTENER + /* start asynchronous program build */ + _program.build(nativeDevices, options, &onProgramBuildComplete, + new detail::ProgramBuild(*this, devices, programBuildListener)); +#else + _program.build(nativeDevices, options); +#endif +} + +void Program::createKernels( + std::vector>& kernels) { + VECTOR_CLASS nativeKernels; + + /* Create kernels */ + _program.createKernels(&nativeKernels); + + /* Wrap kernels */ + kernels.clear(); + kernels.reserve(nativeKernels.size()); + for (auto nativeKernel : nativeKernels) { + kernels.push_back(std::make_shared(nativeKernel)); + } +} + +const std::shared_ptr& Program::context() const { + return _context; +} + +} /* namespace dcld */ diff --git a/daemon/src/Program.h b/daemon/src/Program.h new file mode 100644 index 0000000..ed8de50 --- /dev/null +++ b/daemon/src/Program.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Program.h + * + * \date 2012-07-30 + * \author Philipp Kegel + */ + +#ifndef PROGRAM_H_ +#define PROGRAM_H_ + +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcld { + +class Context; + +/* ****************************************************************************/ + +/*! + * \brief A decorator for a native program. + * + * This wrapper is required to receive program source or binaries from a host + * and for notifying program build listeners about completed programs builds. + */ +class Program: public dcl::Program { +public: + Program( + const std::shared_ptr& context, + const char * source, + size_t length); + Program( + const std::shared_ptr& context, + const std::vector& devices, + const std::vector& lengths, + const unsigned char ** binaries, + VECTOR_CLASS * binary_status); + virtual ~Program(); + + operator cl::Program() const; + + void build( + const std::vector& devices, + const char * options, + const std::shared_ptr& programBuildListener); + + void createKernels( + std::vector>& kernels); + + const std::shared_ptr& context() const; + +private: + /* Programs must be non-copyable */ + Program( + const Program& rhs) = delete; + Program& operator=( + const Program& rhs) = delete; + + std::shared_ptr _context; //!< Context associated with program + + cl::Program _program; //!< Native program +}; + +} /* namespace dcld */ + +#endif /* PROGRAM_H_ */ diff --git a/daemon/src/Session.cpp b/daemon/src/Session.cpp new file mode 100644 index 0000000..3148a8f --- /dev/null +++ b/daemon/src/Session.cpp @@ -0,0 +1,247 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Session.cpp + * + * \date 2013-09-29 + * \author Philipp Kegel + */ + +#include "Session.h" + +#include "CommandQueue.h" +#include "Context.h" +#include "Device.h" +#include "Event.h" +#include "Kernel.h" +#include "Memory.h" +#include "Program.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcld { + +Session::Session(const cl::Platform& platform) : + _platform(platform) { +} + +Session::~Session() { +} + +/* **************************************************************************** + * Session APIs + ******************************************************************************/ + +std::shared_ptr Session::createContext( + dcl::Host& host, + const std::vector& computeNodes, + const std::vector& devices, + const std::shared_ptr& listener) { + auto context = std::make_shared( + std::ref(host), computeNodes, _platform, devices, listener); + _contexts.insert(context); + + return context; +} + +void Session::releaseContext( + const std::shared_ptr& context) { + if (_contexts.erase(context) != 1) { + throw cl::Error(CL_INVALID_CONTEXT); + } +} + +std::shared_ptr Session::createCommandQueue( + const std::shared_ptr& context, + dcl::Device *device, + cl_command_queue_properties properties) { + auto commandQueue = std::make_shared( + std::dynamic_pointer_cast(context), + dynamic_cast(device), + properties); + _commandQueues.insert(commandQueue); + + return commandQueue; +} + +void Session::releaseCommandQueue( + const std::shared_ptr& commandQueue) { + if (_commandQueues.erase(commandQueue) != 1) { + throw cl::Error(CL_INVALID_COMMAND_QUEUE); + } +} + +std::shared_ptr Session::createBuffer( + const std::shared_ptr& context, + cl_mem_flags flags, + size_t size, + void *ptr) { + auto buffer = std::make_shared( + std::dynamic_pointer_cast(context), flags, size, ptr); + _memoryObjects.insert(buffer); + + return buffer; +} + +void Session::releaseMemObject( + const std::shared_ptr& memory) { + if (_memoryObjects.erase(memory) != 1) { + throw cl::Error(CL_INVALID_MEM_OBJECT); + } +} + +std::shared_ptr Session::createProgram( + const std::shared_ptr& context, + const char *source, + size_t length) { + auto program = std::make_shared( + std::dynamic_pointer_cast(context), source, length); + _programs.insert(program); + + return program; +} + +std::shared_ptr Session::createProgram( + const std::shared_ptr& context, + const std::vector& devices, + const std::vector& lengths, + const unsigned char **binaries, + std::vector *binary_status) { + auto program = std::make_shared( + std::dynamic_pointer_cast(context), devices, lengths, binaries, binary_status); + _programs.insert(program); + + return program; +} + +void Session::releaseProgram( + const std::shared_ptr& program) { + if (_programs.erase(program) != 1) { + throw cl::Error(CL_INVALID_PROGRAM); + } +} + +std::shared_ptr Session::createKernel( + const std::shared_ptr& program, + const char *name) { + auto kernel = std::make_shared( + std::dynamic_pointer_cast(program), name); + _kernels.insert(kernel); + + return kernel; +} + +std::vector> Session::createKernelsInProgram( + const std::shared_ptr& program, + cl_uint numKernels) { + if (!program) throw cl::Error(CL_INVALID_PROGRAM); + + std::vector> kernels; + + program->createKernels(kernels); + if (numKernels != kernels.size()) throw cl::Error(CL_INVALID_VALUE); + _kernels.insert(std::begin(kernels), std::end(kernels)); + + return kernels; +} + +void Session::releaseKernel( + const std::shared_ptr& kernel) { + if (_kernels.erase(kernel) != 1) { + throw cl::Error(CL_INVALID_KERNEL); + } +} + +void Session::addEvent( + const std::shared_ptr& event) { + _events.insert(event); +} + +std::shared_ptr Session::createEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects) { + std::vector> memoryObjectImpls; + + /* Verify memory objects */ + memoryObjectImpls.reserve(memoryObjects.size()); + for (auto memoryObject : memoryObjects) { + memoryObjectImpls.push_back(std::dynamic_pointer_cast(memoryObject)); + } + + /* Create event + * Technically, events can only be created by enqueuing a command. However, + * since the command has been enqueued on another compute node, a user + * event is created as a substitute for that event. The status of the + * substitute event is controlled by messages about execution status changes + * of its associated command. */ + auto event = std::make_shared( + id, std::dynamic_pointer_cast(context), memoryObjectImpls); + /* Add event to list */ + _events.insert(event); + + return event; +} + +void Session::releaseEvent( + const std::shared_ptr& event) { + if (_events.erase(event) != 1) { + throw cl::Error(CL_INVALID_EVENT); + } +} + +} /* namespace dcld */ diff --git a/daemon/src/Session.h b/daemon/src/Session.h new file mode 100644 index 0000000..24f3ebb --- /dev/null +++ b/daemon/src/Session.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Session.h + * + * \date 2013-09-29 + * \author Philipp Kegel + */ + +#ifndef SESSION_H_ +#define SESSION_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dcld { + +/*! + * The Session class saves the state of a connected host, i.e., it manages all + * OpenCL objects that have been created on a compute node to implement a + * corresponding OpenCL object on the host. + */ +class Session: public dcl::Session { +public: + /*! + * \brief Creates a session associated with the specified platform. + * + * \param[in] platform the platform associated with this session + */ + Session( + const cl::Platform& platform); + virtual ~Session(); + + /* Session APIs */ + std::shared_ptr createContext( + dcl::Host& host, + const std::vector& computeNodes, + const std::vector& devices, + const std::shared_ptr& listener); + void releaseContext( + const std::shared_ptr& context); + + std::shared_ptr createCommandQueue( + const std::shared_ptr& context, + dcl::Device * device, + cl_command_queue_properties properties); + void releaseCommandQueue( + const std::shared_ptr& commandQueue); + + std::shared_ptr createBuffer( + const std::shared_ptr& context, + cl_mem_flags flags, + size_t size, + void * ptr); + void releaseMemObject( + const std::shared_ptr& memory); + + std::shared_ptr createProgram( + const std::shared_ptr& context, + const char * source, + size_t length); + std::shared_ptr createProgram( + const std::shared_ptr& context, + const std::vector& deviceList, + const std::vector& lengths, + const unsigned char ** binaries, + std::vector * binary_status); + void releaseProgram( + const std::shared_ptr& program); + + std::shared_ptr createKernel( + const std::shared_ptr& program, + const char * name); + std::vector> createKernelsInProgram( + const std::shared_ptr& program, + cl_uint numKernels); + void releaseKernel( + const std::shared_ptr& kernel); + + void addEvent( + const std::shared_ptr& event); + std::shared_ptr createEvent( + dcl::object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects); + void releaseEvent( + const std::shared_ptr& event); + +private: + /* Sessions must be non-copyable */ + Session( + const Session& rhs) = delete; + Session& operator=( + const Session& rhs) = delete; + + cl::Platform _platform; + + std::set> _contexts; //!< Context list + std::set> _memoryObjects; //!< Memory object list + std::set> _commandQueues; //!< Command queue list + std::set> _programs; //!< Program list + std::set> _kernels; //!< Kernel list + std::set> _events; //!< Event list +}; + +} /* namespace dcld */ + +#endif /* SESSION_H_ */ diff --git a/daemon/src/command/Command.h b/daemon/src/command/Command.h new file mode 100644 index 0000000..6a3fb54 --- /dev/null +++ b/daemon/src/command/Command.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Command.h + * + * \date 2012-03-23 + * \author Philipp Kegel + */ + +#ifndef COMMAND_H_ +#define COMMAND_H_ + +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dcld { + +namespace command { + +class Command { +public: + Command( + dcl::Host& host, + dcl::object_id commandId, + const cl::UserEvent& event) : + _host(host), _commandId(commandId), _event(event) { + } + + virtual ~Command() { } + + /*! + * \brief Executes this command. + * + * \param[in] errcode an error code of the operation that triggered this + * command's execution. + */ + virtual void execute( + cl_int errcode) = 0; + +protected: + dcl::Host& _host; + dcl::object_id _commandId; + cl::UserEvent _event; +}; + +} /* namespace command */ + +} /* namespace dcld */ + +#endif /* COMMAND_H_ */ diff --git a/daemon/src/command/CopyDataCommand.h b/daemon/src/command/CopyDataCommand.h new file mode 100644 index 0000000..223018d --- /dev/null +++ b/daemon/src/command/CopyDataCommand.h @@ -0,0 +1,152 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CopyDataCommand.h + * + * \date 2014-01-19 + * \author Philipp Kegel + */ + +#ifndef COPYDATACOMMAND_H_ +#define COPYDATACOMMAND_H_ + +#include "Command.h" + +#include + +#include +#include +#include +#include + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include + +namespace dcld { + +namespace command { + +struct DeviceToHost { + typedef const void *PointerType; + + static std::shared_ptr transferData( + dcl::Host& host, size_t cb, PointerType ptr) { + return host.sendData(cb, ptr); + } +}; + +struct HostToDevice { + typedef void *PointerType; + + static std::shared_ptr transferData( + dcl::Host& host, size_t cb, PointerType ptr) { + return host.receiveData(cb, ptr); + } +}; + +/* ****************************************************************************/ + +template +class CopyDataCommand: public Command { +public: + CopyDataCommand( + dcl::Host& host, + dcl::object_id commandId, + size_t cb, + typename Direction::PointerType ptr, + const cl::UserEvent& event) : + Command(host, commandId, event), _cb(cb), _ptr(ptr) { + } + + void execute( + cl_int errcode) { + assert(errcode == CL_SUCCESS || errcode < 0); + if (errcode == CL_SUCCESS) { + try { + // start data transfer on host + dclasio::message::CommandExecutionStatusChangedMessage message(_commandId, CL_SUBMITTED); + + _host.sendMessage(message); + + dcl::util::Logger << dcl::util::Debug + << "Sent update of command execution status to host (ID=" << _commandId + << ", status=CL_SUBMITTED" + << ')' << std::endl; + + // start local data transfer + /* Copy event to increase reference count. Thus, the user event + * will not be released until the data transfer has been + * completed and updated the event status */ + Direction::transferData(_host, _cb, _ptr)->setCallback(std::bind( + &cl::UserEvent::setStatus, _event, std::placeholders::_1)); + } catch (const dcl::IOException& err) { + dcl::util::Logger << dcl::util::Error + << "Failed to send update of command execution status to host (ID=" << _commandId + << ", status=CL_SUBMITTED)" + << ", error: " << err.what() + << std::endl; + + _event.setStatus(CL_IO_ERROR_WWU); + } + } else { + // forward execution status to associated event + _event.setStatus(errcode); + } + } + +private: + size_t _cb; + typename Direction::PointerType _ptr; +}; + +} /* namespace command */ + +} /* namespace dcld */ + +#endif /* COPYDATACOMMAND_H_ */ diff --git a/daemon/src/command/SetCompleteCommand.cpp b/daemon/src/command/SetCompleteCommand.cpp new file mode 100644 index 0000000..8dc7408 --- /dev/null +++ b/daemon/src/command/SetCompleteCommand.cpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file SetCompleteCommand.cpp + * + * \date 2012-09-11 + * \author Philipp Kegel + */ + +#include "SetCompleteCommand.h" + +#include "Command.h" + +#include + +#include +#include +#include + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include + +namespace dcld { + +namespace command { + +SetCompleteCommand::SetCompleteCommand( + dcl::Host& host, + dcl::object_id commandId, + const cl::UserEvent& event) : + Command(host, commandId, event) { +} + +void SetCompleteCommand::execute(cl_int errcode) { + assert(errcode == CL_SUCCESS || errcode < 0); + + try { + dclasio::message::CommandExecutionStatusChangedMessage message(_commandId, errcode); + + _host.sendMessage(message); + + dcl::util::Logger << dcl::util::Debug + << "Sent update of command execution status to host (ID=" << _commandId + << ", status=" << errcode + << ')' << std::endl; + } catch (const dcl::IOException& err) { + errcode = CL_IO_ERROR_WWU; + dcl::util::Logger << dcl::util::Error + << "Failed to send update of command execution status to host (ID=" << _commandId + << ", status=" << errcode << ')' + << ", error: " << err.what() + << std::endl; + } + + // forward execution status to associated event + _event.setStatus(errcode); +} + +} /* namespace command */ + +} /* namespace dcld */ diff --git a/daemon/src/command/SetCompleteCommand.h b/daemon/src/command/SetCompleteCommand.h new file mode 100644 index 0000000..c8aabf3 --- /dev/null +++ b/daemon/src/command/SetCompleteCommand.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file SetCompleteCommand.h + * + * \date 2012-09-11 + * \author Philipp Kegel + */ + +#ifndef SETCOMPLETECOMMAND_H_ +#define SETCOMPLETECOMMAND_H_ + +#include "Command.h" + +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dcld { + +namespace command { + +class SetCompleteCommand: public Command { +public: + SetCompleteCommand( + dcl::Host& host, + dcl::object_id commandId, + const cl::UserEvent& event); + + /*! + * \brief Sends a command completion message (\c CL_SUCCESS or error code) to the host + */ + void execute( + cl_int errcode); +}; + +} /* namespace command */ + +} /* namespace dcld */ + +#endif /* SETCOMPLETECOMMAND_H_ */ diff --git a/daemon/src/dOpenCLd.cpp b/daemon/src/dOpenCLd.cpp new file mode 100644 index 0000000..0c3be8d --- /dev/null +++ b/daemon/src/dOpenCLd.cpp @@ -0,0 +1,340 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file dOpenCLd.cpp + * + * \date 2011-01-16 + * \author Philipp Kegel + * + * Implementation of dOpenCL daemon + */ + +#include "dOpenCLd.h" + +#include "Device.h" +#include "Session.h" + +#include +#include +#include +#include +#include + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +/*! + * \brief Extracts version information from an OpenCL version string. + * The OpenCL version string is given as + * OpenCL + * + * \param[in] version OpenCL version string + * \param[out] major major version number + * \param[out] minor minor version number + * \param[out] info platform-specific information + */ +void getOpenCLVersion( + const std::string& version, + unsigned int& major, + unsigned int& minor, + std::string& info) { + std::istringstream iss(version); + std::string token; + + /* + * Validate prefix + */ + iss >> token; // read first token + if (token.compare("OpenCL")) { + /* version string does not start with 'OpenCL' */ + throw std::invalid_argument("Invalid OpenCL version string"); + } + + /* + * Extract version numbers + */ + if (iss.eof() || iss.get() != ' ') { // skip space + throw std::invalid_argument("No version number found"); + } + major = 0; + minor = 0; + iss >> major; // read major version number + iss.ignore(); // skip period + iss >> minor; // read minor version number + + if (iss.good()) { + /* + * Extract platform-specific information + */ + if (iss.get() != ' ') { // skip space + throw std::invalid_argument("Invalid version number"); + } + std::getline(iss, info); // read platform-specific information (all remaining characters) + } +} + +cl::Platform getPlatform(const std::string *platformName) { + VECTOR_CLASS platforms; + + /* The number of platform may be zero without throwing an error. + * If an ICD loader is used, CL_PLATFORM_NOT_FOUND_KHR will be thrown. */ + cl::Platform::get(&platforms); + + /* + * Select platform + */ + auto platform = std::begin(platforms); + while (platform != std::end(platforms)) { + std::string version; + unsigned int major, minor; + std::string info; + + /* + * Obtain platform version + * dOpenCL daemon requires OpenCL version 1.1 + */ + platform->getInfo(CL_PLATFORM_VERSION, &version); + getOpenCLVersion(version, major, minor, info); + + if (platformName) { + std::string name; + + /* + * select platform by name + */ + platform->getInfo(CL_PLATFORM_NAME, &name); + if ((name.find(*platformName) != std::string::npos)) { + if (major < 1 || (major == 1 && minor < 1)) { + dcl::util::Logger << dcl::util::Warning + << "Platform '" << name << "' (version " + << version << ") does not support OpenCL 1.1 or higher." + << std::endl; + platform = std::end(platforms); + } + break; + } + } else { + /* + * select first appropriate platform + */ + if ((major == 1 && minor >= 1) || major > 1) { + break; + } + } + + ++platform; + } + + if (platform == std::end(platforms)) { + if (!platforms.empty()) { + dcl::util::Logger << dcl::util::Error + << "No OpenCL 1.1 compliant platform found." << std::endl; + } + throw cl::Error(CL_PLATFORM_NOT_FOUND_KHR); + } + + return *platform; +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dcld { + +dOpenCLd::dOpenCLd(const std::string& url, const std::string *platform) : + _communicationManager(dcl::ComputeNodeCommunicationManager::create(url)), + _platform(getPlatform(platform)) { + initializeDevices(); +} + +dOpenCLd::~dOpenCLd() { +} + +void dOpenCLd::run() { + std::lock_guard lock(_interruptMutex); + + /* attach to connection manager */ + _communicationManager->setDaemon(this); + _communicationManager->addConnectionListener(*this); + + _communicationManager->start(); + + /* TODO Process connections in run method rather than in the callback methods */ + + /* Suspend the calling (main) thread to prevent the daemon from exiting */ + _interrupt = false; + while (!_interrupt) _interrupted.wait(_interruptMutex); + + _communicationManager->stop(); + + /* detach from connection manager */ + _communicationManager->setDaemon(); + _communicationManager->removeConnectionListener(*this); + + dcl::util::Logger << dcl::util::Info + << "Shutting down dOpenCL daemon ..." << std::endl; +} + +void dOpenCLd::terminate() { + std::lock_guard lock(_interruptMutex); + /* Resume the main thread which will terminate the daemon */ + _interrupt = true; + _interrupted.notify_all(); +} + +void dOpenCLd::initializeDevices() { + VECTOR_CLASS devices; + + /* + * Initialize device list + */ + _platform.getDevices(CL_DEVICE_TYPE_ALL, &devices); + + dcl::util::Logger << dcl::util::Info + << "Using platform '" << _platform.getInfo() << "'\n" + << "\tfound " << devices.size() << " device(s):\n"; + for (auto device : devices) { + dcl::util::Logger << dcl::util::Info + << "\t\t" << device.getInfo() << '\n'; + _devices.push_back(std::unique_ptr(new Device(device))); + } + dcl::util::Logger.flush(); +} + +/* **************************************************************************** + * dOpenCL compute node/daemon API + ******************************************************************************/ + +void dOpenCLd::getDevices( + std::vector& devices) const { + devices.reserve(_devices.size()); + for (const auto& device : _devices) { + devices.push_back(device.get()); + } +} + +dcl::Session * dOpenCLd::getSession( + const dcl::Host& host) const { + auto i = _sessions.find(&host); + return (i == std::end(_sessions)) ? nullptr : i->second.get(); +} + +/* **************************************************************************** + * dOpenCL connection listener API + ******************************************************************************/ + +bool dOpenCLd::connected(dcl::Host& host) { + std::lock_guard lock(_sessionsMutex); + + auto i = _sessions.find(&host); + if (i == std::end(_sessions)) { + /* create new session in list */ + bool created = _sessions.emplace( + &host, std::unique_ptr(new Session(_platform))).second; + if (created) { + dcl::util::Logger << dcl::util::Info + << "Session created (host='" << host.url() << "')" << std::endl; + } + return created; + } else { + /* TODO Handle reestablished connection */ + return true; + } +} + +void dOpenCLd::disconnected(dcl::Host& host) { + std::lock_guard lock(_sessionsMutex); + + /* TODO Retain session for future reconnect + * Do not drop a session if its process has lost connection. Rather preserve + * the session to allow the process to reconnect and continue the session. + * Only drop sessions on request, or after a certain timeout has expired. */ + + auto i = _sessions.find(&host); + if (i != std::end(_sessions)) { + /* FIXME Handle incomplete events when destroying a session */ + /* If a user event status is not set to completed the daemon hangs + * permanently within clReleaseContext when destroying the session. + * Presumably because the native OpenCL implementation waits for the + * event status to become CL_COMPLETE, which never happens for user + * events after the application on the client has been terminated. */ + _sessions.erase(i); // remove session from list + + dcl::util::Logger << dcl::util::Info + << "Session destroyed (host='" << host.url() << "')" << std::endl; + } + + /* TODO Delete host when disconnected + * The ownership of the host must be clarified, as the host may be used by + * multiple connection listeners. + * Possible solution: return bool (see connected) to indicate if host should + * be deleted. If all listeners agree on deleting the host, it is deleted + * by the communication manager. */ +} + +bool dOpenCLd::connected(dcl::ComputeNode& computeNode) { + /* TODO Implement dOpenCLd::connected for compute nodes */ + return false; +} + +void dOpenCLd::disconnected(dcl::ComputeNode& computeNode) { + /* TODO Implement dOpenCLd::disconnected for compute nodes */ +} + +} /* namespace dcld */ diff --git a/daemon/src/dOpenCLd.h b/daemon/src/dOpenCLd.h new file mode 100644 index 0000000..0ac5b97 --- /dev/null +++ b/daemon/src/dOpenCLd.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file dOpenCLd.h + * + * \date 2011-01-16 + * \author Philipp Kegel + * + * dOpenCL daemon + */ + +#ifndef DOPENCLD_H_ +#define DOPENCLD_H_ + +#include +#include +#include +#include +#include +#include +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +namespace dcld { + +class Device; +class Session; + +/* ****************************************************************************/ + +class dOpenCLd: public dcl::Daemon, public dcl::ConnectionListener { +public: + /*! + * \brief Creates a daemon. + * + * \param[in] url URL which the daemon should bind to + * \param[in] platformName name of the platform which the daemon should attach to + * If platformName is \c NULL, the first platform available will be used. + */ + dOpenCLd( + const std::string& url, + const std::string *platform = nullptr); + virtual ~dOpenCLd(); + + /*! + * \brief Does what the daemon does. + * + * This is a blocking method. Use terminate to return from this call. + */ + void run(); + + /*! + * \brief Terminates the daemon. + * + * This method signals the daemon to stop gracefully. + */ + void terminate(); + + /* + * compute node/daemon API + */ + void getDevices( + std::vector& devices) const; + + dcl::Session * getSession( + const dcl::Host& host) const; + + /* + * dOpenCL connection listener API + */ + bool connected( + dcl::Host& host); + void disconnected( + dcl::Host& host); + bool connected( + dcl::ComputeNode& computeNode); + void disconnected( + dcl::ComputeNode& computeNode); + +private: + /* Daemons must be non-copyable */ + dOpenCLd( + const dOpenCLd& rhs) = delete; + dOpenCLd& operator=( + const dOpenCLd&) = delete; + + void initializeDevices(); + + std::unique_ptr _communicationManager; + + cl::Platform _platform; //!< Selected platform; default is first platform + std::vector> _devices; //!< Device list + + bool _interrupt; + std::mutex _interruptMutex; + std::condition_variable_any _interrupted; + + std::map> _sessions; //!< Sessions + mutable std::mutex _sessionsMutex; +}; + +} /* namespace dcld */ + +#endif /* DOPENCLD_H_ */ diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp new file mode 100644 index 0000000..7183fb3 --- /dev/null +++ b/daemon/src/main.cpp @@ -0,0 +1,280 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file main.cpp + * + * \date 2011-01-16 + * \author Philipp Kegel + * + * Start program of dOpenCL daemon + */ + +#ifdef DAEMON +// feature test macro for lockf +#define _BSD_SOURCE +#endif +// feature test macro for sigaction +#define _POSIX_SOURCE + +#include "dOpenCLd.h" + +#include + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +#ifdef DAEMON +#include +#include +#include + +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) +#include +#endif + +std::unique_ptr dcl_daemon; //!< dOpenCL daemon + +#if defined(_POSIX_VERSION) +void install_signal_handlers(); +#endif + +/* ****************************************************************************/ + +void terminate(int signum) { + assert(signum == SIGINT || signum == SIGTERM); + if (!dcl_daemon) return; + dcl_daemon->terminate(); +} + +int main(int argc, char **argv) { + boost::program_options::variables_map vm; + std::string platform; + std::string url; + + try { + boost::program_options::options_description options("Allowed options"); + boost::program_options::options_description arguments("Allowed arguments"); + boost::program_options::options_description all("Usage: dcld [options] "); + boost::program_options::positional_options_description p; + + // specify program options + options.add_options() + ("help", "produce help message") + ("platform,p", boost::program_options::value(&platform), + "OpenCL platform to use") + ; + arguments.add_options() + ("hostname", boost::program_options::value(&url), + "daemon interface") + ; + all.add(options).add(arguments); + + // specify positional arguments + p.add("hostname", 1); + + // parse program options + boost::program_options::store(boost::program_options::command_line_parser( + argc, argv).options(all).positional(p).run(), vm); + + if (vm.count("help")) { + std::cout << all << std::endl; + return EXIT_SUCCESS; + } + + boost::program_options::notify(vm); + } catch (const boost::program_options::error& err) { + std::cerr << err.what() << std::endl; + return EXIT_FAILURE; + } + +#ifdef DAEMON + /* TODO Create a true daemon; see + * http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html + * http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/fork/daemon.cpp + * http://openbook.galileocomputing.de/linux_unix_programmierung/Kap07-011.htm#RxxKap07011040002021F048100 + */ + + // Fork off the parent process + if (pid_t pid = fork()) { + if (pid < 0) { + syslog(LOG_ERR | LOG_USER, "Cannot fork daemon process: %m"); + return EXIT_FAILURE; + } else { + /* exit the parent process */ + return EXIT_SUCCESS; + } + } + + /* + * now we are in the first child process + */ + + /* Make the process the leader of a new session in order to detach it from + * the controlling terminal */ + if (setsid() < 0) { + syslog(LOG_ERR | LOG_USER, "Failed to create session: %m"); + return EXIT_FAILURE; + } + + /* Fork off the parent process again to ensure that the new process cannot + * acquire a controlling terminal */ + if (pid_t pid = fork()) { + if (pid < 0) { + syslog(LOG_ERR | LOG_USER, "Second fork failed: %m"); + return EXIT_FAILURE; + } else { + return EXIT_SUCCESS; // exit the parent process + } + } + + /* + * now we are in the second child process, which is the actual daemon process + */ + + // change the current working directory + if ((chdir("/tmp")) < 0) { + syslog(LOG_ERR | LOG_USER, "Cannot change working directory: %m"); + return EXIT_FAILURE; + } + + umask(0); // change the file mode mask + + // use file lock to ensure mutual exclusion of multiple daemon instances + int lock_file = open("/tmp/dcld.lock", O_RDWR | O_CREAT, 0640); + if (lock_file < 0) { + syslog(LOG_ERR | LOG_USER, "Cannot open lock file: %m"); + return EXIT_FAILURE; + } + if (lockf(lock_file, F_TLOCK, 0) < 0) { + // another daemon instance is already running + return EXIT_SUCCESS; + } + // write PID to lock file +// sprintf(str, "%d\n", getpid()); +// write(lock_file, str, strlen(str)); + + // close standard file descriptors + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + // reopen standard file descriptors and forward to /dev/null + int fd = open("/dev/null", O_RDWR); // STDIN + dup(fd); // STDOUT + dup(fd); // STDERR + + /* open system log + * Use system log for standard messages and log all the rest into dedicated + * log files */ +// openlog("dcld", LOG_PID | LOG_CONS | LOGNDELAY, LOG_DAEMON); +#endif + + // install event handlers +#if defined(_WIN32) + // TODO Use messages for event handling in Windows +#else +#if defined(_POSIX_VERSION) + // Use signals for event handling in POSIX-compliant OS's + install_signal_handlers(); +#endif +#endif + + /* + * start daemon + */ + try { + // create daemon instance + dcl_daemon.reset(new dcld::dOpenCLd(url, + (vm.count("platform") ? &platform : nullptr))); + dcl_daemon->run(); + dcl_daemon.reset(); // destroy daemon + } catch (const dcl::DCLException& err) { + std::cerr << err.what() << std::endl; + return EXIT_FAILURE; + } catch (const cl::Error& err) { + switch (err.err()) { + case CL_PLATFORM_NOT_FOUND_KHR: // no platforms were found + std::cerr << "Platform not found." << std::endl; + break; + default: + std::cerr << "OpenCL error: " << err.err() << std::endl; + // no break + } + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +/* ****************************************************************************/ + +#if defined(_POSIX_VERSION) +void install_signal_handlers() { + struct sigaction no_action, terminate_action; + + no_action.sa_handler = SIG_IGN; + sigemptyset(&no_action.sa_mask); + no_action.sa_flags = 0; + + terminate_action.sa_handler = &terminate; + sigemptyset(&terminate_action.sa_mask); + sigaddset(&terminate_action.sa_mask, SIGINT); // block INT signal during termination + sigaddset(&terminate_action.sa_mask, SIGTERM); // block TERM signal during termination + terminate_action.sa_flags = 0; + + sigaction(SIGHUP, &no_action, nullptr); // ignore SIGHUP, no config file to read + sigaction(SIGINT, &terminate_action, nullptr); // 'program interrupt', e.g., user pressed Ctrl-C + sigaction(SIGTERM, &terminate_action, nullptr); // default signal to terminate program +} +#endif /* defined(_POSIX_VERSION) */ diff --git a/dclasio/CMakeLists.txt b/dclasio/CMakeLists.txt new file mode 100644 index 0000000..759db22 --- /dev/null +++ b/dclasio/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 2.6) + +project(dOpenCLlib) + +option(BUILD_SHARED_LIBS "Build shared library" ON) + +# search for Boost System Library (required by Boost.Asio) +find_package(Boost 1.35.0 COMPONENTS system REQUIRED) + +# search for Doxygen +find_package(Doxygen) + +# create lists of source files and headers +file(GLOB CL_WWU_HEADERS ${PROJECT_SOURCE_DIR}/include/CL *.h) +file(GLOB_RECURSE DCL_SOURCES ${PROJECT_SOURCE_DIR}/src/dcl *.cpp) +file(GLOB_RECURSE DCL_HEADERS ${PROJECT_SOURCE_DIR}/include/dcl *.h) +file(GLOB_RECURSE DCLASIO_SOURCES ${PROJECT_SOURCE_DIR}/src/dclasio *.cpp) + +# include project headers +include_directories(${PROJECT_SOURCE_DIR}/include + ${Boost_INCLUDE_DIRS}) + +link_directories(${Boost_LIBRARY_DIRS}) + + +# +# dOpenCL library target +# + +add_library(dcl ${DCL_SOURCES} ${DCLASIO_SOURCES}) +target_link_libraries(dcl + ${Boost_LIBRARIES}) + +# enable OpenCL 1.1 compatibility +set_property(TARGET dcl + PROPERTY COMPILE_DEFINITIONS + CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +if(BUILD_SHARED_LIBS) +# set library version and SONAME + set_target_properties(dcl PROPERTIES + VERSION 0.4.0 + SOVERSION 0) +else(BUILD_SHARED_LIBS) +# compile static library using -fPIC, such that it can be linked with a shared +# library, namely the dOpenCL ICD + set_target_properties(dcl PROPERTIES + COMPILE_FLAGS -fPIC) +endif(BUILD_SHARED_LIBS) + + +# +# Documentation target +# + +# TODO Warn if Doxygen has not been found +# replace CMake variable in the Doxyfile.in template thereby generating Doxyfile +configure_file(${PROJECT_SOURCE_DIR}/doc/Doxyfile.in + ${PROJECT_BINARY_DIR}/doc/Doxyfile @ONLY) +# run Doxygen in build directory using the generated Doxyfile +add_custom_target(doc + ${DOXYGEN_EXECUTABLE} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc + COMMENT "Generating dOpenCL API documentation") + + +# +# install configuration +# + +install(TARGETS dcl + RUNTIME DESTINATION lib + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + +# TODO Install OpenCL API extension headers +#install(FILES ${CL_WWU_HEADERS} DESTINATION include/CL) +# TODO Install dOpenCL API headers +#install(FILES ${DCL_HEADERS} DESTINATION include/dcl) +# TODO Install dOpenCL API documentation diff --git a/dclasio/doc/Doxyfile.in b/dclasio/doc/Doxyfile.in new file mode 100644 index 0000000..df8206b --- /dev/null +++ b/dclasio/doc/Doxyfile.in @@ -0,0 +1,1781 @@ +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "dOpenCL" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.4.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "An implementation of the OpenCL API for distributed systems" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @PROJECT_BINARY_DIR@/doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/include + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @PROJECT_SOURCE_DIR@/include/dcl @PROJECT_SOURCE_DIR@/include/dcl/comm + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which isq +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = @DOXYGEN_DOT_PATH@ + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/dclasio/include/CL/README.txt b/dclasio/include/CL/README.txt new file mode 100644 index 0000000..b9f05dc --- /dev/null +++ b/dclasio/include/CL/README.txt @@ -0,0 +1,19 @@ +*** WARNING *** +This folder must not contain the standard OpenCL headers, but only the headers of the dOpenCL API extension. +*** WARNING *** + +This folder is specified as an additional include directory for all dOpenCL +projects, as these require the definition of the dOpenCL API extension. If any +standard OpenCL header is also added to this folder it overrides the system's +OpenCL headers. This causes serious linker issues in the daemon, when the OpenCL +version of the headers (in this folder) and the system's installed OpenCL +implementation differ. +The daemon project is implemented in such a way that it implements all OpenCL +API functions that are provided on the local system (detected using the +CL_VERSION_... macros). If the OpenCL header version is greater than the version +of the system's OpenCL implementation, the linker will not find all required +symbols for linking. Some symbol are implicitly required by the OpenCL C++ +binding, even if the daemon is not using these symbols directly. + +Make sure that the OpenCL headers and OpenCL C++ binding are installed that +correspond to the target system's OpenCL implementation. \ No newline at end of file diff --git a/dclasio/include/CL/cl_wwu_collective.h b/dclasio/include/CL/cl_wwu_collective.h new file mode 100644 index 0000000..f192dd8 --- /dev/null +++ b/dclasio/include/CL/cl_wwu_collective.h @@ -0,0 +1,255 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl_wwu_collective.h + * + * @date 2012-07-06 + * @author Philipp Kegel + * + * OpenCL API extension for collective operations + */ + +#ifndef CL_WWU_COLLECTIVE_H_ +#define CL_WWU_COLLECTIVE_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define cl_wwu_collective 1 + +/******************************************************************************/ + +/* cl_command_type */ +#define CL_COMMAND_BROADCAST_BUFFER_WWU 0x1300 +#define CL_COMMAND_REDUCE_BUFFER_WWU 0x1301 + +/* cl_kernel_arg_placeholder */ +#define CL_KERNEL_ARG_1 0x1 +#define CL_KERNEL_ARG_2 0x2 + +/******************************************************************************/ + +/* Collective operation APIs */ + +/** + * @brief Broadcasts host memory to a set of buffers. + * This operation is equivalent to a number of calls of clEnqueueWriteBuffer + * where the same host memory is copied to multiple destination buffers. + * A command queue has to be specified for each destination buffer in order to + * determine the device where the buffer is migrated to. + * Upload is performed in two steps: 1) upload host memory to compute node; + * 2) upload data to buffers using clEnqueueWriteBuffer. + * + * @param[in] command_queue_list a list of command queues + * @param[in] num_buffers number of destination buffers + * @param[in] buffer_list the buffers to broadcast to (receive buffers) + * @param[in] offsets + * @param[in] cb the number of bytes to broadcast + * @param[in] ptr pointer to host memory that should be broadcasted + * @param[in] num_events_in_wait_list + * @param[in] event_wait_list + * @param[out] event + * @return error code + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWriteBuffersWWU( + cl_command_queue * /* command_queue_list */, + cl_uint /* num_buffers */, + cl_mem * /* buffer_list */, + const size_t * /* offsets */, + size_t /* cb */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Broadcasts a buffer to a set of buffers. + * This operation is equivalent to a number of calls of clEnqueueCopyBuffer + * where the same source buffer is copied to multiple destination buffers. + * A command queue has to be specified for each destination buffer in order to + * determine the device where the buffer is migrated to. Actually, a 'copy + * buffer' operation is issued to this command queue. + * Data is only copied between compute nodes by means of the memory consistency + * protocol. + * + * @param[in] command_queue_list a list of command queues + * @param[in] src_buffer the buffer to broadcast (send buffer) + * @param[in] num_dst_buffer number of destination buffers + * @param[in] dst_buffer_list the buffers to broadcast to (receive buffers) + * @param[in] src_offset + * @param[in] dst_offset_list + * @param[in] cb the number of bytes to broadcast + * @param[in] num_events_in_wait_list + * @param[in] event_wait_list + * @param[out] event + * @return error code + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueBroadcastBufferWWU( + cl_command_queue * /* command_queue_list */, + cl_mem /* src_buffer */, + cl_uint /* num_dst_buffers */, + cl_mem * /* dst_buffer_list */, + size_t /* src_offset */, + const size_t * /* dst_offset_list */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Reduces a set of buffers into a single buffer + * + * @param[in] command_queue command queue for writing destination buffer + * @param[in] num_src_buffers number of buffers to reduce + * @param[in] src_buffer_list the buffers to reduce (send buffers) + * @param[in] dst_buffer the buffers to reduce into (receive buffer) + * @param[in] kernel a kernel for reducing two buffers + * This kernel must accept at least two arguments, but may also use + * more. The two mandatory arguments must be CL_KERNEL_ARG_1 and + * CL_KERNEL_ARG_2. + * @param[in] work_dim + * @param[in] global_work_offset + * @param[in] global_work_size + * @param[in] local_work_size + * @param[in] num_events_in_wait_list + * @param[in] event_wait_list + * @param[out] event + * @return error code + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReduceBufferWWU( + cl_command_queue /* command_queue */, + cl_uint /* num_src_buffers */, + cl_mem * /* src_buffer_list */, + cl_mem /* dst_buffer */, +// const size_t * /* src_offset_list */, +// size_t /* dst_offset */, +// size_t /* cb */, + cl_kernel /* kernel */, + cl_uint /* work_dim */, + const size_t * /* global_work_offset */, + const size_t * /* global_work_size */, + const size_t * /* local_work_size */, +// cl_reduce_operator_WWU /* operator */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_EXT_SUFFIX__VERSION_1_1; + +/* + * Not all collectives known from MPI are reasonable in OpenCL, because memory + * objects are shared by all devices of a context. + * + * Scattering a buffer is equivalent to dividing a buffer into sub-buffers, + * while gathering buffers means addressing a buffer which had been 'scattered' + * into sub-buffers. Moreover, as all devices share the sub-buffers' associated + * buffer, 'gather' would actually mean 'all-gather'. + * Hence, the following collectives are not required in OpenCL: + * * clEnqueueScatterBufferWWU + * * clEnqueueGatherBufferWWU + * * clEnqueueAllGatherBufferWWU + * + * Collectives in OpenCL will implicitly provide their result for all devices. + * Hence, the following collectives are not required in OpenCL: + * * clEnqueueAllReduceBufferWWU (just use clEnqueueReduceBufferWWU; the + * reduced buffer is accessible by all devices.) + * + * Collectives that include one of the aforementioned redundant collectives, + * also are not required. This holds for: + * * clEnqueueReduceScatterBufferWWU (just use clEnqueueReduceBufferWWU and + * define sub-buffers for the reduced buffer.) + */ + +/******************************************************************************/ + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueWriteBuffersWWU_fn)( + cl_command_queue * /* command_queue_list */, + cl_uint /* num_buffers */, + cl_mem * /* buffer_list */, + const size_t * /* offsets */, + size_t /* cb */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */); + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueBroadcastBufferWWU_fn)( + cl_command_queue * /* command_queue_list */, + cl_mem /* src_buffer */, + cl_uint /* num_dst_buffers */, + cl_mem * /* dst_buffer_list */, + size_t /* src_offset */, + const size_t * /* dst_offset_list */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */); + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReduceBufferWWU_fn)( + cl_command_queue /* command_queue */, + cl_uint /* num_src_buffers */, + cl_mem * /* src_buffer_list */, + cl_mem /* dst_buffer */, +// const size_t * /* src_offset_list */, +// size_t /* dst_offset */, +// size_t /* cb */, + cl_kernel /* kernel */, + cl_uint /* work_dim */, + const size_t * /* global_work_offset */, + const size_t * /* global_work_size */, + const size_t * /* local_work_size */, +// cl_reduce_operator_WWU /* oper */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */); + +#ifdef __cplusplus +} +#endif + +#endif /* CL_WWU_COLLECTIVE_H_ */ diff --git a/dclasio/include/CL/cl_wwu_collective.txt b/dclasio/include/CL/cl_wwu_collective.txt new file mode 100644 index 0000000..c4afd9a --- /dev/null +++ b/dclasio/include/CL/cl_wwu_collective.txt @@ -0,0 +1,140 @@ +XXX - Not complete yet!!! + + + +Name Strings + + cl_wwu_collective + +Contributors + + Philipp Kegel + Michel Steuwer + +Contact + + Philipp Kegel + Michel Steuwer + +IP Status + + No known claims. + +Version + + Version 1, July 15, 2012 + +Number + + TBD + + <"TBD" until the extension is completed and posted to the + Khronos Registry> + +Status + + Incomplete - DO NOT SHIP + + + +Extension Type + + OpenCL platform extension + +Dependencies + + OpenCL 1.1 is required + + _". Also describe which release of the OpenCL + specification document this extension is written against.> + +Overview + + + +Header File + + + +New Procedures and Functions + + as + in the extension name, but the should be uppercase instead + of lowercase, e.g. "clNewFunctionKHR".> + +New Tokens + + as + new entry points. Precede tokens by a summary of which functions + they are used in and how. Examples: + + Returned by clCreateContext when an invalid OpenCL context + is specified in properties: + + CL_INVALID_GL_CONTEXT_KHR 0x???? + + Accepted as the argument of clGetGLContextInfoKHR: + + CL_CGL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x???? + > + +Additions to Chapter NNN / Appendix AAA of the OpenCL Specification + + + +Interactions with other extensions + + _" followed by a summary of the + interaction.> + +Issues + + + +Sample Code + + + +Conformance Tests + + + +Revision History + + diff --git a/dclasio/include/CL/cl_wwu_dcl.h b/dclasio/include/CL/cl_wwu_dcl.h new file mode 100644 index 0000000..71f7dfc --- /dev/null +++ b/dclasio/include/CL/cl_wwu_dcl.h @@ -0,0 +1,342 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl_wwu_dcl.h + * + * @date 2011-04-12 + * @author Philipp Kegel + * + * OpenCL API extension for distributed execution + * + * This API extension has three layers: + * 1) Static and transparent compute node management; + * 2) Dynamic compute node management; + * 3) Dynamic device management. + * + * The first layer only introduces compute nodes into the OpenCL platform model. + * Compute nodes can be obtained from a platform, and information on these + * compute nodes can be queried by the application. + * Compute nodes cannot be added or removed by the application, but are + * statically configured using a node file on the host and the compute nodes. + * This approach is fully transparent and compatible with OpenCL applications. + * + * The second layer facilitates dynamic compute node management. An application + * can create or release compute nodes within a platform. This also implicates + * that devices can be retained or released by the application such that compute + * nodes are only removed from the platform if no device that is associated with + * that compute node will be used by the application anymore. + * + * The third layer facilitates dynamic device management. An application can + * create devices such that a resource manager adds appropriate compute nodes + * from a cloud to a given platform. + */ + +#ifndef CL_WWU_DCL_H_ +#define CL_WWU_DCL_H_ + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define cl_wwu_dcl 1 + +/* Additional error codes */ +#define CL_INVALID_NODE_FILE_WWU -2001 +#define CL_INVALID_NODE_NAME_WWU -2002 +#define CL_INVALID_NODE_WWU -2003 +#define CL_CONNECTION_ERROR_WWU -2004 +#define CL_IO_ERROR_WWU -2005 +#define CL_PROTOCOL_ERROR_WWU -2006 + +/******************************************************************************/ + +typedef struct _cl_compute_node_WWU * cl_compute_node_WWU; + +typedef cl_uint cl_compute_node_info_WWU; + +typedef intptr_t cl_device_properties_WWU; + +/* cl_compute_node_info_WWU */ +#define CL_NODE_PLATFORM_WWU 0x0800 +#define CL_NODE_REFERENCE_COUNT_WWU 0x0801 +#define CL_NODE_URL_WWU 0x0802 +#define CL_NODE_PROFILE_WWU 0x0803 +#define CL_NODE_VERSION_WWU 0x0804 +#define CL_NODE_NAME_WWU 0x0805 +#define CL_NODE_VENDOR_WWU 0x0806 +#define CL_NODE_EXTENSIONS_WWU 0x0807 +#define CL_NODE_AVAILABLE_WWU 0x0808 + +/* cl_device_info */ +#define CL_DEVICE_COMPUTE_NODE_WWU 0x1040 + +#ifndef CL_VERSION_1_2 +/* cl_program_info */ +/* Provide CL_PROGRAM_NUM_KERNELS for forward compatibility of OpenCL 1.1 */ +#define CL_PROGRAM_NUM_KERNELS 0x1167 + +/* cl_command_type */ +/* Provide CL_COMMAND_BARRIER for forward compatibility of OpenCL 1.1 */ +#define CL_COMMAND_BARRIER 0x1205 +#endif + +/* cl_profiling_info */ +#define CL_PROFILING_COMMAND_RECEIVED_WWU 0x1284 + +/******************************************************************************/ + +/* Compute node APIs */ +/* TODO Specify compute node semantics + * a) A compute node is regarded a simple device provider + * b) A compute node is regarded an access point for a network of device providers + */ + +/** + * @brief Adds a compute node to a platform. + * + * @param[in] platform the platform the newly created compute node is added to. + * Refers to the platform ID returned by clGetPlatformIDs or can be NULL. + * If platform is NULL, the behavior is implementation-defined. + * @param[in] url the URL of the compute node to add + * @param[in] pfn_notify A callback function that can be registered by the application. + * This callback function will be used by the OpenCL implementation to report information on errors that occur during communication with this compute node. + * This callback function may be called asynchronously by the OpenCL implementation. + * It is the application's responsibility to ensure that the callback function is thread-safe. + * If pfn_notify is NULL, no callback function is registered. + * @param[in] user_data + * @param[out] errcode_ret error code + * @return a compute node, or NULL if the compute node URL is invalid + */ +extern CL_API_ENTRY cl_compute_node_WWU CL_API_CALL +clCreateComputeNodeWWU( + cl_platform_id /* platform */, + const char * /* url */, + void (* /* pfn_notify */)( + cl_compute_node_WWU /* compute_node */, + cl_int /* connection_status */, + void * /* user_data */), + void * /* user_data */, + cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Increments a compute node's reference counter. + * + * @param[in] compute_node compute node + * @return error code + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainComputeNodeWWU( + cl_compute_node_WWU /* compute_node */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Decrements a compute node's reference counter, removing the compute node from its platform if the counter becomes 0. + * + * @param[in] compute_node compute node + * @return error code + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseComputeNodeWWU( + cl_compute_node_WWU /* compute_node */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Returns a list of compute nodes. + * + * @param[in] platform + * @param[in] num_entries + * @param[out] compute_nodes + * @param[out] num_compute_nodes + * @return + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clGetComputeNodesWWU( + cl_platform_id /* platform */, + cl_uint /* num_entries */, + cl_compute_node_WWU* /* compute_nodes */, + cl_uint * /* num_compute_nodes */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Returns the specified information on a given compute node. + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clGetComputeNodeInfoWWU( + cl_compute_node_WWU /* compute_node */, + cl_compute_node_info_WWU /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_EXT_SUFFIX__VERSION_1_1; + +/* Context APIs */ + +extern CL_API_ENTRY cl_context CL_API_CALL +clCreateContextFromComputeNodesWWU( + const cl_context_properties * /* properties */, + cl_int /* num_compute_nodes */, + const cl_compute_node_WWU * /* compute_nodes */, + void (CL_CALLBACK * /* pfn_notify*/ )( + const char *, const void *, size_t, void *), + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1; + +/* Extended device APIs */ + +/** + * @brief Obtain the list of devices available on a particular compute node. + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceIDsFromComputeNodeWWU( + cl_compute_node_WWU /* compute_node */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Allocates devices from the resource manager's device pool. + * + * CL_INVALID_PROPERTY if device property name in properties is not a supported + * property name, if the value specified for a supported property name is not + * valid, or if the same property name is specified more than once. + * + * @param[in] platform the platform the newly created compute node is added to. + * Refers to the platform ID returned by clGetPlatformIDs or can be NULL. + * If platform is NULL, the behavior is implementation-defined. + * @param[in] properties Specifies a list of device property names and their + * corresponding values. Each property name is immediately followed + * by the corresponding desired value. The list is terminated with 0. + * properties can be NULL in which case the device that is returned + * is implementation-defined. The list of supported properties is + * described in the table below. + * @param[in] num_devices + * @param[in] devices + * @param[out] num_devices_ret + * @return error code + */ +extern CL_API_ENTRY cl_int CL_API_CALL +clCreateDevicesWWU( + cl_platform_id /* platform */, + cl_device_properties_WWU /* properties */, + size_t /* num_devices */, + cl_device_id * /* devices */, + size_t /* num_device_ret */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Increments a device's reference counter. + * + * @param[in] device device + * @return error code + */ +/* TODO Merge clRetainDeviceWWU with clRetainDevice (OpenCL 1.2) */ +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainDeviceWWU( + cl_device_id /* device */) CL_EXT_SUFFIX__VERSION_1_1; + +/** + * @brief Decrements a device's reference counter, removing it from its platform if the counter becomes 0. + * + * The returned device will no longer be available to the application, i.e. any + * reference to this device will be regarded invalid. + * + * @param[in] device the device to return + * @return error code + */ +/* TODO Merge clRetainDeviceWWU with clRetainDevice (OpenCL 1.2) */ +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseDeviceWWU( + cl_device_id /* device */) CL_EXT_SUFFIX__VERSION_1_1; + +/******************************************************************************/ + +typedef CL_API_ENTRY cl_compute_node_WWU (CL_API_CALL *clCreateComputeNodeWWU_fn)( + const char * /* url */, + void (* /* pfn_notify */)( + cl_compute_node_WWU /* compute_node */, + cl_int /* connection_status */, + void * /* user_data */), + void * /* user_data */, + cl_int * /* errcode_ret */); +typedef CL_API_ENTRY cl_int (CL_API_CALL *clRetainComputeNodeWWU_fn)( + cl_compute_node_WWU /* compute_node */); +typedef CL_API_ENTRY cl_int (CL_API_CALL *clReleaseComputeNodeWWU_fn)( + cl_compute_node_WWU /* compute_node */); +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetComputeNodesWWU_fn)( + cl_platform_id /* platform */, + cl_uint /* num_entries */, + cl_compute_node_WWU * /* compute_nodes */, + cl_uint * /* num_compute_nodes */); +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetComputeNodeInfoWWU_fn)( + cl_compute_node_WWU /* compute_node */, + cl_compute_node_info_WWU /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */); + +typedef CL_API_ENTRY cl_context (CL_API_CALL *clCreateContextFromComputeNodesWWU_fn)( + const cl_context_properties * /* properties */, + cl_int /* num_compute_nodes */, + const cl_compute_node_WWU * /* compute_nodes */, + void (CL_CALLBACK * /* pfn_notify*/ )( + const char *, const void *, size_t, void *), + void * /* user_data */, + cl_int * /* errcode_ret */); + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clCreateDevicesWWU_fn)( + cl_platform_id /* platform */, + cl_device_properties_WWU /* properties */, + size_t /* num_devices */, + cl_device_id * /* devices */, + size_t /* num_device_ret */); +typedef CL_API_ENTRY cl_int (CL_API_CALL *clRetainDeviceWWU_fn)( + cl_device_id /* device */); +typedef CL_API_ENTRY cl_int (CL_API_CALL *clReleaseDeviceWWU_fn)( + cl_device_id /* device */); + +#ifdef __cplusplus +} +#endif + +#endif /* CL_WWU_DCL_H_ */ diff --git a/dclasio/include/CL/cl_wwu_dcl.txt b/dclasio/include/CL/cl_wwu_dcl.txt new file mode 100644 index 0000000..dde305f --- /dev/null +++ b/dclasio/include/CL/cl_wwu_dcl.txt @@ -0,0 +1,140 @@ +XXX - Not complete yet!!! + + + +Name Strings + + cl_wwu_dcl + +Contributors + + Philipp Kegel + Michel Steuwer + +Contact + + Philipp Kegel + Michel Steuwer + +IP Status + + No known claims. + +Version + + Version 1, July 15, 2012 + +Number + + TBD + + <"TBD" until the extension is completed and posted to the + Khronos Registry> + +Status + + Incomplete - DO NOT SHIP + + + +Extension Type + + OpenCL platform extension + +Dependencies + + OpenCL 1.1 is required + + _". Also describe which release of the OpenCL + specification document this extension is written against.> + +Overview + + + +Header File + + + +New Procedures and Functions + + as + in the extension name, but the should be uppercase instead + of lowercase, e.g. "clNewFunctionKHR".> + +New Tokens + + as + new entry points. Precede tokens by a summary of which functions + they are used in and how. Examples: + + Returned by clCreateContext when an invalid OpenCL context + is specified in properties: + + CL_INVALID_GL_CONTEXT_KHR 0x???? + + Accepted as the argument of clGetGLContextInfoKHR: + + CL_CGL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x???? + > + +Additions to Chapter NNN / Appendix AAA of the OpenCL Specification + + + +Interactions with other extensions + + _" followed by a summary of the + interaction.> + +Issues + + + +Sample Code + + + +Conformance Tests + + + +Revision History + + diff --git a/dclasio/include/dcl/Binary.h b/dclasio/include/dcl/Binary.h new file mode 100644 index 0000000..4b554c0 --- /dev/null +++ b/dclasio/include/dcl/Binary.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Binary.h + * + * \date 2011-10-15 + * \author Philipp Kegel + */ + +#ifndef BINARY_H_ +#define BINARY_H_ + +#include +#include +#include +#include + +namespace dcl { + +/*! + * \brief A container for a sequence of bytes. + * + * This class is used to store, e.g., object info or kernel arguments. + * It is similar to std::string, but stores bytes rather than characters. + */ +class Binary { +public: + /*! + * \brief Creates an empty binary object. + */ + Binary() : + _size(0), _value(nullptr) { + } + + // FIXME sizeof is not portable + template + Binary(const T& value) : + _size(sizeof(T)), + _value(new char[sizeof(T)]) /* allocate memory for value */ { + ::memcpy(_value, &value, _size); // copy value + } + + Binary(size_t size, const void *value) : + _size(size), + _value(new char[size]) /* allocate memory for value */ { + ::memcpy(_value, value, _size); // copy value + } + + Binary(const Binary& rhs) : + _size(rhs._size), + _value(new char[rhs._size]) /* allocate memory for value */ { + ::memcpy(_value, rhs._value, rhs._size); // copy value + } + + Binary(Binary&& rhs) : + _size(rhs._size), _value(rhs._value) { + /* detach data from rvalue */ + rhs._size = 0; + rhs._value = nullptr; + } + + ~Binary() { + delete[] _value; + } + + /*! + * \brief Performs a byte-wise comparison. + * + * \param[in] rhs the binary to compare this binary with + * \return \c true, if this binary equals rhs, otherwise \c false + */ + bool operator==(const Binary& rhs) const { + return ((_size == rhs._size) && + (::memcmp(_value, rhs._value, _size) == 0)); + } + + bool operator!=(const Binary& rhs) const { + return !(*this == rhs); + } + + void assign(size_t size, const void *value) { + /* FIXME Handle self assignment in dcl::Binary::assign */ + + if (_size != size) { + char *mem = new char[size]; // allocate memory for new value + delete[] _value; // delete current value + + _size = size; + _value = mem; + } + + /* initialize or overwrite current value */ + ::memcpy(_value, value, size); + } + + Binary& operator=(const std::pair& param) { + assign(param.first, param.second); + return *this; + } + + Binary& operator=(const Binary& rhs) { + if (this != &rhs) { + assign(rhs._size, rhs._value); + } + return *this; + } + + /*! + * \brief Move assignment operator. + * + * This operator swaps the values of two binaries. + * + * \param[inout] rhs value to move + * \return a reference to this binary + */ + Binary& operator=(Binary&& rhs) { + assert(this != &rhs); // a temporary should always be unique + /* swap value to ensure that rhs deletes current value */ + std::swap(_size, rhs._size); + std::swap(_value, rhs._value); + return *this; + } + + size_t size() const { + return _size; + } + + const void * value() const { + return _value; + } + +private: + size_t _size; + char *_value; +}; + +} /* namespace dcl */ + +#endif /* BINARY_H_ */ diff --git a/dclasio/include/dcl/BlockingQueue.h b/dclasio/include/dcl/BlockingQueue.h new file mode 100644 index 0000000..edbe900 --- /dev/null +++ b/dclasio/include/dcl/BlockingQueue.h @@ -0,0 +1,146 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file BlockingQueue.h + * + * \date 2011-03-10 + * \author Philipp Kegel + */ + +#ifndef BLOCKINGQUEUE_H_ +#define BLOCKINGQUEUE_H_ + +#include "DCLException.h" + +#include +#include +#include +#include + +namespace dcl { + +/*! + * \brief A thread-safe blocking queue + */ +template::container_type > +class BlockingQueue: private std::queue { +public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + + bool empty() const { + std::lock_guard lock(_mutex); + return std::queue::empty(); + } + + size_type size() const { + std::lock_guard lock(_mutex); + return std::queue::size(); + } + + value_type& front() { + std::lock_guard lock(_mutex); + awaitElement(); + return std::queue::front(); + } + + const value_type& front() const { + std::lock_guard lock(_mutex); + awaitElement(); + return std::queue::front(); + } + + value_type& back() { + std::lock_guard lock(_mutex); + awaitElement(); + return std::queue::back(); + } + + const value_type& back() const { + std::lock_guard lock(_mutex); + awaitElement(); + return std::queue::back(); + } + + void push(const T& x) { + std::lock_guard lock(_mutex); + std::queue::push(x); + /* all waiting threads have to be notified as multiple calls of, e.g., + * front can be valid even with only a single element. */ + _modified.notify_all(); + } + + void pop() { + std::lock_guard lock(_mutex); + + awaitElement(); + std::queue::pop(); + } + + void interrupt() { + std::lock_guard lock(_mutex); + _interrupt = true; + _modified.notify_all(); + } + +private: + mutable std::mutex _mutex; + std::condition_variable_any _modified; + + bool _interrupt; + + /*! + * \brief Waits for the queue to become non-empty + * + * This methods blocks until an element has been added to the queue, or + * interrupt is called. + */ + void awaitElement() { + _interrupt = false; + + while (std::queue::empty() && !_interrupt) { + _modified.wait(_mutex); + } + + if (_interrupt) throw ThreadInterrupted(); + } + +}; + +} /* namespace dcl */ + +#endif /* BLOCKINGQUEUE_H_ */ diff --git a/dclasio/include/dcl/ByteBuffer.h b/dclasio/include/dcl/ByteBuffer.h new file mode 100644 index 0000000..fc67da1 --- /dev/null +++ b/dclasio/include/dcl/ByteBuffer.h @@ -0,0 +1,324 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ByteBuffer.h + * + * \date 2014-03-20 + * \author Philipp Kegel + */ + +#ifndef DCL_BYTEBUFFER_H_ +#define DCL_BYTEBUFFER_H_ + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +/*! + * \brief Serialization type traits + */ +template struct serialization; +template<> struct serialization { static const size_t size = sizeof(cl_char); }; // 8 bit +template<> struct serialization { static const size_t size = sizeof(cl_uchar); }; // 8 bit +template<> struct serialization { static const size_t size = sizeof(cl_short); }; // 16 bit +template<> struct serialization { static const size_t size = sizeof(cl_ushort); }; // 16 bit +template<> struct serialization { static const size_t size = sizeof(cl_int); }; // 32 bit +template<> struct serialization { static const size_t size = sizeof(cl_uint); }; // 32 bit +template<> struct serialization { static const size_t size = sizeof(cl_long); }; // 64 bit +template<> struct serialization { static const size_t size = sizeof(cl_ulong); }; // 64 bit +template<> struct serialization { static const size_t size = sizeof(float); }; // 32 bit +template<> struct serialization { static const size_t size = sizeof(double); }; // 64 bit + +} // anonymous namespace + +/* ****************************************************************************/ + +namespace dcl { + +/*! + * \brief A simple de-/serialization facility + * This class is able to serialize the following types: + * + OpenCL API types (cl_int, cl_uint, cl_ulong, ...), + * + float, double, + * + size_t, + * + C strings, std::string, and + * + std::vector, where T is any serializable type. + * Network byte order is used for serialized representation to ensure portability. + * Deserialization is *not* type-safe, i.e., it is the caller's responsibility + * to extract serialized data correctly. + * This class is not thread-safe for performance reasons. + */ +class ByteBuffer { +public: + typedef char value_type; + typedef uint32_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type * pointer; + typedef const value_type * const_pointer; + typedef value_type * iterator; + typedef const value_type * const_iterator; + + const static size_type DEFAULT_SIZE = 512; //!< default buffer size in bytes + const static size_type DEFAULT_MAX_SIZE = 65536; //!< default maximum buffer size in bytes + +private: + /*! + * \brief Resizes the buffer to the specified internal size. + * \param[in] size the new internal buffer size + * \throw std::out_of_range if \c size exceeds max_size + */ + inline void reserve( + size_type size) { + if (size > _max_size) throw std::out_of_range("Internal buffer overflow"); + if (size <= _size) return; // no operation + /* TODO Resize buffer + * First, try to recover memory of read bytes just by moving content to beginning + * If this does not provide enough space, increase buffer size before moving content bytes to beginning */ + assert(!"resize not implemented"); + } + + /*! + * \brief Ensures that at least \c size bytes can be written to the buffer + * \param[in] free the number of bytes to write + */ + inline void ensure_free( + size_type free) { + auto size = _len + free; + if (size > _size) { // ensure required buffer size + while (size < _size) { + size *= 2; // double buffer size + } + reserve(std::max(std::min(size, _max_size), free)); + } + } + + /*! + * \brief Ensures that at least \c size bytes can be read from the buffer + * \param[in] size the number of bytes to read + * \throw std::out_of_range if less than \c size bytes can be read from the buffer + */ + inline void ensure_bytes( + size_type size) { + if ((_len - _pos) < size) throw std::out_of_range("Buffer underflow"); + } + + ByteBuffer(const ByteBuffer& other) = delete; + +public: + ByteBuffer(); + /*! + * \brief Creates a buffer with the specified number of reserved bytes + * The buffer size as returned by ByteBuffer::size is 0. + * \param[in] initial_size the internal size of the byte buffer + */ + ByteBuffer( + size_type initial_size); + /*! + * \brief Creates a buffer from raw bytes + * The buffer becomes owner of the bytes - it does *not* copy the bytes. + * \param[in] size the number of bytes + * \param[in] bytes the raw bytes + */ + ByteBuffer( + size_type size, + value_type bytes[]); + ByteBuffer( + ByteBuffer&& other); + virtual ~ByteBuffer(); + + /*! + * \brief Restricts the buffer's maximum size to the specified value + * \param[in] max_size the buffer's maximum size + */ + void set_max_size( + size_type max_size); + + template + ByteBuffer& operator<<( + const T& value) { + ensure_free(serialization::size); + // TODO Convert to network byte order + // TODO Use std::copy + memcpy(_bytes.get() + _len, &value, serialization::size); + _len += serialization::size; + return *this; + } + + ByteBuffer& operator<<( + const bool flag); +#if USE_CSTRING + ByteBuffer& operator<<( + const char *str); +#endif + ByteBuffer& operator<<( + const std::string& str); + ByteBuffer& operator<<( + const Binary& data); + + /*! + * \brief Serializes a vector of serializable values + * \param[in] values the vector to serialize + * \return this byte buffer + */ + template + ByteBuffer& operator<<( + const std::vector& values) { + operator<<(values.size()); // write number of elements + for (const auto& value : values) { + operator<<(value); + } + return *this; + } + + /*! + * \brief Serializes a map of serializable values + * \param[in] pairs the map of key-value-pairs to serialize + * \return this byte buffer + */ + template + ByteBuffer& operator<<( + const std::map& pairs) { + operator<<(pairs.size()); // write number of pairs + for (const auto& pair : pairs) { + operator<<(pair.first); + operator<<(pair.second); + } + return *this; + } + + template + ByteBuffer& operator>>( + T& value) { + ensure_bytes(serialization::size); + // TODO Convert to host byte order + // TODO Use std::copy + memcpy(&value, _bytes.get() + _pos, serialization::size); + _pos += serialization::size; + return *this; + } + + ByteBuffer& operator>>( + bool& flag); +#if USE_CSTRING + ByteBuffer& operator>>( + char *str); +#endif + ByteBuffer& operator>>( + std::string& str); + ByteBuffer& operator>>( + Binary& data); + + template + ByteBuffer& operator>>( + std::vector& values) { + size_t size; + operator>>(size); // read number of elements + values.resize(size); + for (auto& value : values) { + // remove const qualifier from value to update it from byte buffer + operator>>(const_cast::type>(value)); + } + return *this; + } + + template + ByteBuffer& operator>>( + std::map& pairs) { + size_t size; + operator>>(size); // read number of pairs + pairs.clear(); + for (size_t i = 0; i < size; ++i) { + // remove const qualifiers from key and value to update them from byte buffer + typename std::remove_const::type key; + typename std::remove_const::type value; + operator>>(key); + operator>>(value); + pairs.insert(std::make_pair(std::move(key), std::move(value))); + // TODO std::map::emplace does not compile with GCC 4.6 +// pairs.emplace(std::move(key), std::move(value)); + } + return *this; + } + + /*! + * \brief Resizes the buffer to the specified size + * The buffer's content is undefined after this operation. + * Usually, this method is used before overwriting the buffer directly using an iterator. + * \param[in] size the new buffer size + */ + void resize( + size_type size); + + size_type size() const; + + iterator begin(); + const_iterator begin() const; + const_iterator cbegin() const; + + iterator end(); + const_iterator end() const; + const_iterator cend() const; + +private: + size_type _pos; // read count + size_type _len; // write count, i.e., size of buffer content *including* the read bytes + size_type _max_size; + size_type _size; // buffer size + std::unique_ptr _bytes; // buffer data +}; + +} // namespace dcl + +#endif /* DCL_BYTEBUFFER_H_ */ diff --git a/dclasio/include/dcl/CLError.h b/dclasio/include/dcl/CLError.h new file mode 100644 index 0000000..3deb0cb --- /dev/null +++ b/dclasio/include/dcl/CLError.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLError.h + * + * \date 2012-02-27 + * \author Philipp Kegel + */ + +#ifndef CLERROR_H_ +#define CLERROR_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dcl { + +/*! + * \brief An exception representing an OpenCL error code. + */ +class CLError: public std::exception { +public: + CLError( + cl_int err, + const char *what = nullptr) throw (); + CLError( + cl_int err, + const std::string& what) throw (); + virtual ~CLError() throw(); + + /*! + * \brief Gets the error string associated with this exception. + * + * \return a memory pointer to the error message string. + */ + virtual const char * what() const throw (); + + /*! + * \brief Gets the error code associated with this exception. + * + * \return the error code + */ + cl_int err() const throw(); + +protected: + cl_int _err; + std::string _what; +}; + +} /* namespace dcl */ + +#endif /* CLERROR_H_ */ diff --git a/dclasio/include/dcl/CLObjectRegistry.h b/dclasio/include/dcl/CLObjectRegistry.h new file mode 100644 index 0000000..185b16c --- /dev/null +++ b/dclasio/include/dcl/CLObjectRegistry.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLObjectRegistry.h + * + * \date 2012-07-12 + * \author Philipp Kegel + */ + +#ifndef CLOBJECTREGISTRY_H_ +#define CLOBJECTREGISTRY_H_ + +#include "DCLTypes.h" + +#include + +namespace dcl { + +namespace detail { + +template +class Registry { +public: + void bind( + object_id id, + T& object); + void unbind( + object_id id); + T * lookup( + object_id id) const; + +private: + std::map _objects; +}; + +} /* namespace detail */ + +/* ****************************************************************************/ + +class CommandListener; +class CommandQueueListener; +class ContextListener; +class ProgramBuildListener; +class SynchronizationListener; + +/* ****************************************************************************/ + +/*! + * \brief A lookup facility for obtaining objects by their associated ID. + * + * It is the central resolver for object IDs. + */ +class CLObjectRegistry: + private detail::Registry, + private detail::Registry, + private detail::Registry, + private detail::Registry, + private detail::Registry { +public: + CLObjectRegistry(); + virtual ~CLObjectRegistry(); + + /*! + * \brief Associates an ID with an object. + * + * \param[in] id the ID to assign + * \param[in] object the object to assign + */ + template + void bind(object_id id, T& object) { + detail::Registry::bind(id, object); + } + + /*! + * \brief Delete the association of the specified ID. + * + * \param[in] id the ID which association should be deleted + */ + template + void unbind(object_id id) { + detail::Registry::unbind(id); + } + + /*! + * \brief Looks up the object that is associated with the specified ID. + * + * \param[in] id the ID of the object to look up + * \return the object associated with ID, or \c NULL if no object is associated with id + */ + template + T * lookup(object_id id) const { + return detail::Registry::lookup(id); + } +}; + +} /* namespace dcl */ + +#endif /* CLOBJECTREGISTRY_H_ */ diff --git a/dclasio/include/dcl/CommandListener.h b/dclasio/include/dcl/CommandListener.h new file mode 100644 index 0000000..00611e1 --- /dev/null +++ b/dclasio/include/dcl/CommandListener.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandListener.h + * + * \date 2011-08-07 + * \author Philipp Kegel + */ + +#ifndef DCL_COMMANDLISTENER_H_ +#define DCL_COMMANDLISTENER_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dcl { + +/*! + * \brief An listener API for command status changes + * + * This API is usually implemented by event objects in order to monitor the execution status of their associated command. + * However, this API is also used to control command execution within the dOpenCL runtime system + */ +class CommandListener { +public: + virtual ~CommandListener() { } + + /*! + * \brief Callback for incoming command execution status change notifications. + * + * \param[in] executionStatus new command execution status + */ + virtual void onExecutionStatusChanged( + cl_int executionStatus) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_COMMANDLISTENER_H_ */ diff --git a/dclasio/include/dcl/CommandQueue.h b/dclasio/include/dcl/CommandQueue.h new file mode 100644 index 0000000..d7c9fce --- /dev/null +++ b/dclasio/include/dcl/CommandQueue.h @@ -0,0 +1,196 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandQueue.h + * + * \date 2012-08-05 + * \author Philipp Kegel + * + * dOpenCL command queue API + */ + +#ifndef DCL_COMMANDQUEUE_H_ +#define DCL_COMMANDQUEUE_H_ + +#include "DCLTypes.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcl { + +class Buffer; +class ComputeNode; +class Event; +class Kernel; +class Memory; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface of a command queue + */ +class CommandQueue { +public: + virtual ~CommandQueue() { } + + virtual void flush() = 0; + + /*! + * \brief Blocks until all previously queued OpenCL commands in this command queue are issued to the associated device and have completed. + * + * This method is a synchronization point. + */ + virtual void finish() = 0; + + virtual void enqueueCopyBuffer( + const std::shared_ptr& src, + const std::shared_ptr& dst, + size_t srcOffset, + size_t dstOffset, + size_t size, + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + + virtual void enqueueReadBuffer( + const std::shared_ptr& buffer, + bool blockingRead, + size_t offset, + size_t size, + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + + virtual void enqueueWriteBuffer( + const std::shared_ptr& buffer, + bool blockingWrite, + size_t offset, + size_t size, + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + + virtual void enqueueMapBuffer( + const std::shared_ptr& buffer, + bool blockingMap, + cl_map_flags mapFlags, + size_t offset, + size_t size, + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + + virtual void enqueueUnmapBuffer( + const std::shared_ptr& buffer, + cl_map_flags mapFlags, + size_t offset, + size_t size, + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + + /*! + * \brief Enqueues a kernel to this + * + * \param[in] kernel kernel to enqueue + * \param[in] offset global work offset + * \param[in] global global work size + * \param[in] local local work size + * \param[in] eventWaitList event to wait for before executing the enqueued kernel + * \param[in] commandId command ID + * \param[out] event event associated with this command, or \c NULL + * + * global work offset, global work size, and local work size must all have + * the same number of entries (i.e., the same dimension) + */ + virtual void enqueueNDRangeKernel( + const std::shared_ptr& kernel, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + + /*! + * \brief Enqueues a marker to this command queue + * + * \param[in] eventWaitList a list of events the marker waits for + * \param[in] commandId an ID that remote event listeners associate with this command + * \param[out] event an event associated with the enqueued marker + */ + virtual void enqueueMarker( + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + /*! + * \brief Enqueues a wait for a specific event or a list of events to complete before any future commands queued in the command-queue are executed. + */ + virtual void enqueueWaitForEvents( + const std::vector>& eventList) = 0; +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + + /*! + * \brief A synchronization point that enqueues a barrier operation. + * + * This method is a synchronization point. Note, however that according to + * Section 3.4.3 of the OpenCL specification, a barrier can only be used to + * synchronize between commands in a single command-queue. + * + * \param[in] eventWaitList + * \param[in] commandId + * \param[out] event + */ + virtual void enqueueBarrier( + const std::vector> * eventWaitList, + object_id commandId, + std::shared_ptr * event) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_COMMANDQUEUE_H_ */ diff --git a/dclasio/include/dcl/CommandQueueListener.h b/dclasio/include/dcl/CommandQueueListener.h new file mode 100644 index 0000000..ff4bbbf --- /dev/null +++ b/dclasio/include/dcl/CommandQueueListener.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandQueueListener.h + * + * \date 2012-08-21 + * \author Philipp Kegel + */ + +#ifndef DCL_COMMANDQUEUELISTENER_H_ +#define DCL_COMMANDQUEUELISTENER_H_ + +namespace dcl { + +/*! + * \brief Remote command queue listener API + * + * A command queue listener subscribes for events of a particular command queue. + */ +class CommandQueueListener { +public: + virtual ~CommandQueueListener() { } + + /*! + * \brief Signals that a command queue has been finished on the compute node. + */ + virtual void onFinish() = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_COMMANDQUEUELISTENER_H_ */ diff --git a/dclasio/include/dcl/CommunicationManager.h b/dclasio/include/dcl/CommunicationManager.h new file mode 100644 index 0000000..385b22a --- /dev/null +++ b/dclasio/include/dcl/CommunicationManager.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommunicationManager.h + * + * \date 2011-08-07 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef COMMUNICATIONMANAGER_H_ +#define COMMUNICATIONMANAGER_H_ + +#include +#include + +namespace dcl { + +class CLObjectRegistry; +class ComputeNode; +class ConnectionListener; +class Daemon; + +/* ****************************************************************************/ + +/*! + * \brief Virtual base class for communication managers. + */ +class CommunicationManager { +public: + virtual ~CommunicationManager() { + } + + /*! + * \brief Starts the communication infrastructure + */ + virtual void start() = 0; + + /*! + * \brief Shuts down the communication infrastructure + */ + virtual void stop() = 0; +}; + +/* ****************************************************************************/ + +/*! + * \brief Communication manager for host processes. + */ +class HostCommunicationManager: public virtual CommunicationManager { +public: + /*! + * \brief Creates a new communication manager which is used for outgoing connections only. + * + * \return a communication manager instance + */ + static HostCommunicationManager * create(); + + virtual ~HostCommunicationManager() { } + + /* TODO Do not expose object registry in public API */ + virtual CLObjectRegistry& objectRegistry() = 0; + + /*! + * \brief Creates a new compute node. + * + * A connection to this compute is created automatically. + * + * \param[in] url the compute node's URL + * \return a compute node instance + */ + virtual ComputeNode * createComputeNode( + const std::string& url) = 0; + + /*! + * \brief Creates multiple compute nodes concurrently. + * + * This method is more efficient for creating multiple compute nodes than + * creating each compute node separately using createComputeNode as the + * creation process is parallelized. + * + * \param[in] urls the compute nodes' URLs + * \param[out] computeNodes compute node instances + */ + virtual void createComputeNodes( + const std::vector& urls, + std::vector& computeNodes) = 0; + + /*! + * \brief Destroys a compute node. + * + * \param[in] computeNode the compute node to destroy + */ + virtual void destroyComputeNode( + ComputeNode *computeNode) = 0; +}; + +/* ****************************************************************************/ + +/*! + * \brief Communication manager for compute node processes. + */ +class ComputeNodeCommunicationManager: public virtual CommunicationManager { +public: + /*! + * \brief Creates a new communication manager which is accessible via a given URL. + * + * \param[in] url URL of the communication manager + * \return a communication manager instance + */ + static ComputeNodeCommunicationManager * create( + const std::string& url); + + virtual ~ComputeNodeCommunicationManager() { } + + virtual void setDaemon( + Daemon *daemon = nullptr) = 0; + + /* TODO Connections should be established transparently in dOpenCL. + * No connection listener should be required in ICD or daemon */ + virtual bool addConnectionListener( + ConnectionListener& listener) = 0; + virtual bool removeConnectionListener( + ConnectionListener& listener) = 0; +}; + +} /* namespace dcl */ + +#endif /* COMMUNICATIONMANAGER_H_ */ diff --git a/dclasio/include/dcl/ComputeNode.h b/dclasio/include/dcl/ComputeNode.h new file mode 100644 index 0000000..7212b92 --- /dev/null +++ b/dclasio/include/dcl/ComputeNode.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ComputeNode.h + * + * \date 2011-10-30 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef DCL_COMPUTENODE_H_ +#define DCL_COMPUTENODE_H_ + +#include "Process.h" + +/* TODO Remove message classes from ComputeNode interface */ +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dcl { + +class Binary; +class Device; + +/* ****************************************************************************/ + +class ComputeNode: public virtual Process { +public: + virtual ~ComputeNode() { } + + /*! + * \brief Obtains a list of devices that are hosted by the compute node. + * + * \param[out] devices a list of devices associated with this compute node + */ + virtual void getDevices( + std::vector& devices) = 0; + + virtual void getInfo( + cl_compute_node_info_WWU param_name, + Binary& param) const = 0; + + /*! + * \brief Sends a request message to this compute node. + * + * \param[in] request the request to send + */ + virtual void sendRequest( + dclasio::message::Request& request) const = 0; + + /*! + * \brief Waits for this compute node's response to the specified request. + * + * This methods throws a dcl::ProtocolException, if the response does not + * have the expected type. + * + * \param[in] request the sent request + * \param[in] responseType the expected type of response + * \return the received response + */ + virtual std::unique_ptr awaitResponse( + const dclasio::message::Request& request, + dclasio::message::Response::class_type responseType) = 0; + /*! + * \brief Waits for this compute node's response to the specified request. + * + * The expected response is Response::TYPE, i.e., a simple response which + * only contains an error code. + * + * \param[in] request the sent request + */ + virtual void awaitResponse( + const dclasio::message::Request& request) = 0; + + /*! + * \brief Execute a command on this compute node. + * + * This methods throws a dcl::ProtocolException, if the response does not + * have the expected type. + * + * \param[in] request the request to send + * \param[in] responseType the expected type of response + * \return the received response + */ + virtual std::unique_ptr executeCommand( + dclasio::message::Request& request, + dclasio::message::Response::class_type responseType) = 0; + + /*! + * \brief Execute a command on this compute node. + * + * The expected response for this command is Response::TYPE, i.e., a simple + * response which only contains an error code. + * + * \param[in] request the request to send + */ + virtual void executeCommand( + dclasio::message::Request& request) = 0; +}; + +/* ****************************************************************************/ + +/* The following function are free functions to avoid hiding of virtual methods. + * E.g., if sendMessage becomes a static member function of ComputeNode, it + * hides the virtual sendMessage which ComputeNode inherits from Process. */ + +/* TODO Discard ComputeNode::sendMessage + * Use ComputeNodeImpl::sendMessage instead */ +void sendMessage( + const std::vector& computeNodes, + dclasio::message::Message& message); + +/* TODO Discard ComputeNode::sendRequest + * Use ComputeNodeImpl::sendRequest instead */ +void sendRequest( + const std::vector& computeNodes, + dclasio::message::Request& request); + +/* TODO Discard ComputeNode::executeCommand + * Use ComputeNodeImpl::executeCommand instead */ +void executeCommand( + const std::vector& computeNodes, + dclasio::message::Request& request, + dclasio::message::Response::class_type responseType = dclasio::message::DefaultResponse::TYPE, + std::vector> * responses = nullptr); + +} /* namespace dcl */ + +#endif /* DCL_COMPUTENODE_H_ */ diff --git a/dclasio/include/dcl/ConnectionListener.h b/dclasio/include/dcl/ConnectionListener.h new file mode 100644 index 0000000..8edfc5b --- /dev/null +++ b/dclasio/include/dcl/ConnectionListener.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ConnectionListener.h + * + * \date 2011-08-07 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef DCL_CONNECTIONLISTENER_H_ +#define DCL_CONNECTIONLISTENER_H_ + +namespace dcl { + +class Host; +class ComputeNode; + +/* ****************************************************************************/ + +class ConnectionListener { +public: + virtual ~ConnectionListener() { } + + /*! + * \brief Callback for incoming host connections. + * + * \param[in] host an incoming host connection + * \return \c true, if the host connection has been accepted, otherwise \c false + */ + virtual bool connected( + Host& host) = 0; + + /*! + * \brief Callback for closed host connections. + * + * \param[in] host a closed host connection + */ + virtual void disconnected( + Host& host) = 0; + + /*! + * \brief Callback for incoming compute node connections. + * + * \param[in] compute node an incoming compute node connection + * \return \c true, if the compute node connection has been accepted, otherwise \c false + */ + virtual bool connected( + ComputeNode& computeNode) = 0; + + /*! + * \brief Callback for closed compute node connections. + * + * \param[in] compute node a closed compute node connection + */ + virtual void disconnected( + ComputeNode& computeNode) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_CONNECTIONLISTENER_H_ */ diff --git a/dclasio/include/dcl/Context.h b/dclasio/include/dcl/Context.h new file mode 100644 index 0000000..e499bc4 --- /dev/null +++ b/dclasio/include/dcl/Context.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Context.h + * + * \date 2012-07-07 + * \author Philipp Kegel + * + * dOpenCL context API + */ + +#ifndef DCL_CONTEXT_H_ +#define DCL_CONTEXT_H_ + +#if 0 +#include "DCLTypes.h" + +#include +#include +#include + +#endif + +namespace dcl { + +class ComputeNode; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface of a context + * + * The context interface it used by both host and compute nodes, but only + * compute nodes should call the sole method Context::raiseError of this + * interface, while only the host should implement this method. + */ +class Context { +public: + virtual ~Context() { } + +#if 0 + virtual void raiseError( + const std::string& errorInfo, + const void * private_info, + size_t cb) = 0; + + /* TODO Delete dcl::Context::getId when all remote ICD objects are accessible through interface classes. */ + virtual dcl::object_id getId() const = 0; + /* TODO Delete dcl::Context::getComputeNodes when all remote ICD objects are accessible through interface classes. */ + virtual void getComputeNodes( + std::vector& computeNodes) const = 0; +#endif +}; + +} /* namespace dcl */ + +#endif /* DCL_CONTEXT_H_ */ diff --git a/dclasio/include/dcl/ContextListener.h b/dclasio/include/dcl/ContextListener.h new file mode 100644 index 0000000..00b1903 --- /dev/null +++ b/dclasio/include/dcl/ContextListener.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ContextListener.h + * + * \date 2012-03-27 + * \author Sebastian Pribnow + * \author Philipp Kegel + */ + +#ifndef DCL_CONTEXTLISTENER_H_ +#define DCL_CONTEXTLISTENER_H_ + +#include + +namespace dcl { + +/*! + * \brief Remote context listener API + * + * A context listener is informed when an error occurs in a particular context. + */ +class ContextListener { +public: + virtual ~ContextListener() { } + + /*! + * \brief Notifies a listener about an error that occurred in a context. + */ + virtual void onError( + const char *errorInfo, + const void *private_info, + size_t cb) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_CONTEXTLISTENER_H_ */ diff --git a/dclasio/include/dcl/DCLException.h b/dclasio/include/dcl/DCLException.h new file mode 100644 index 0000000..620b6c6 --- /dev/null +++ b/dclasio/include/dcl/DCLException.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DCLException.h + * + * \date 2012-02-12 + * \author Philipp Kegel + */ + +#ifndef DCLEXCEPTION_H_ +#define DCLEXCEPTION_H_ + +#include +#include + +/* Error codes */ +#define DCL_SUCCESS 0 +#define DCL_CONNECTION_ERROR -2001 +#define DCL_IO_ERROR -2002 +#define DCL_PROTOCOL_ERROR -2003 +#define DCL_INVALID_CONNECTION_MANAGER -2051 +#define DCL_INVALID_HOST -2052 +#define DCL_INVALID_CONNECTION_LISTENER -2053 +#define DCL_INVALID_COMMAND_LISTENER -2054 +#define DCL_INVALID_DEVICE_MANAGER -2055 +#define DCL_INVALID_NODE -2056 + +/* ****************************************************************************/ + +namespace dcl { + +class DCLException : public std::exception { +public: + DCLException( + const char *what = nullptr) throw (); + DCLException( + const std::string& what) throw (); + virtual ~DCLException() throw(); + + /*! + * \brief Gets the error string associated with this exception. + * + * \return a memory pointer to the error message string. + */ + virtual const char * what() const throw (); + +protected: + std::string _what; +}; + +/* ****************************************************************************/ + +template +class BasicException: public DCLException { +public: + static const int Type = N; + + BasicException( + const char *what = nullptr) throw (); + BasicException( + const std::string& what) throw (); +}; + +typedef BasicException ConnectionException; +typedef BasicException IOException; +typedef BasicException ProtocolException; + +/* ****************************************************************************/ + +class InvalidArgument: public DCLException { +public: + InvalidArgument( + int /* err */, + const char *what = nullptr) throw (); + InvalidArgument( + int /* err */, + const std::string& /* what */) throw (); + virtual ~InvalidArgument() throw(); + + /*! + * \brief Gets the error code associated with this exception. + * + * \return the error code + */ + int err() const throw(); + +protected: + int _err; +}; + +/* ****************************************************************************/ + +/*! + * \brief A class to indicate an interrupted blocking thread + */ +class ThreadInterrupted : public DCLException { +public: + ThreadInterrupted( + const char *what = nullptr) throw (); + ThreadInterrupted( + const std::string& what) throw (); + virtual ~ThreadInterrupted() throw(); +}; + +} /* DCLEXCEPTION_H_ */ + +#endif /* DCLERROR_H_ */ diff --git a/dclasio/include/dcl/DCLTypes.h b/dclasio/include/dcl/DCLTypes.h new file mode 100644 index 0000000..8b154bd --- /dev/null +++ b/dclasio/include/dcl/DCLTypes.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DCLTypes.h + * + * \date 2011-02-05 + * \author Philipp Kegel + * + * dOpenCL C++ API type declarations + */ + +#ifndef DCLTYPES_H_ +#define DCLTYPES_H_ + +#include + +namespace dcl { + +typedef uint32_t object_id; //!< a application object identifier +typedef uint32_t process_id; //!< a unique process identifier + +enum class kernel_arg_type { + BINARY, MEMORY, SAMPLER +}; //!< A kernel argument type + +} /* namespace dcl */ + +#endif /* DCLTYPES_H_ */ diff --git a/dclasio/include/dcl/Daemon.h b/dclasio/include/dcl/Daemon.h new file mode 100644 index 0000000..d990c9b --- /dev/null +++ b/dclasio/include/dcl/Daemon.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Daemon + * + * \date 2013-10-18 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef DCL_DAEMON_H_ +#define DCL_DAEMON_H_ + +#include + +namespace dcl { + +class Device; +class Host; +class Session; + +/* ****************************************************************************/ + +/*! + * An interface class to access a compute node's devices and sessions. + * + * This interface is a tentative solution to avoid implementing the current + * ComputeNode interface on the compute node side as the interface contains some + * unwanted compatibility methods (e.g., sendRequest, etc.). + * + * This interface should be integrated into the ComputeNode interface as the + * daemon actually is a representation of a compute node. + */ +class Daemon { +public: + virtual ~Daemon() { } + + /*! + * \brief Returns a list of compute nodes available on the compute node + * + * \param[out] devices a list of available compute nodes + */ + virtual void getDevices( + std::vector& devices) const = 0; + + /*! + * \brief Looks up the session that is associated with \c host + * + * \param[in] host the host which session should be returned + * \return the host's session, or \c NULL if no session is associated with \c host + */ + virtual Session * getSession( + const Host& host) const = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_DAEMON_H_ */ diff --git a/dclasio/include/dcl/DataTransfer.h b/dclasio/include/dcl/DataTransfer.h new file mode 100644 index 0000000..e5e1db2 --- /dev/null +++ b/dclasio/include/dcl/DataTransfer.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DataTransfer.h + * + * \date 2011-12-17 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef DATATRANSFER_H_ +#define DATATRANSFER_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dcl { + +/*! + * \brief A handle for an asynchronous data transfer. + */ +class DataTransfer { +public: + virtual ~DataTransfer() { } + + /*! + * \brief Registers a callback which is called upon completion (or failure) + * of this data transfer. + * + * \param[in] notify the callback to register + */ + virtual void setCallback( + const std::function& notify) = 0; + + virtual unsigned long submit() const = 0; + virtual unsigned long start() const = 0; + virtual unsigned long end() const = 0; + + virtual bool isComplete() const = 0; + + /*! + * \brief Blocks until this data transfer is complete. + */ + virtual void wait() const = 0; + + /*! + * \brief Aborts this data transfer. + * + * The data transfer is considered as failed after calling this method. + * All registered callbacks are called accordingly. + */ + virtual void abort() = 0; +}; + +} /* namespace dcl */ + +#endif /* DATATRANSFER_H_ */ diff --git a/dclasio/include/dcl/Device.h b/dclasio/include/dcl/Device.h new file mode 100644 index 0000000..9068365 --- /dev/null +++ b/dclasio/include/dcl/Device.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Device.h + * + * \date 2011-11-12 + * \author Philipp Kegel + */ + +#ifndef DCL_DEVICE_H_ +#define DCL_DEVICE_H_ + +#include "DCLTypes.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dcl { + +class Binary; +class ComputeNode; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface for a device + */ +class Device { +public: + virtual ~Device() { } + + virtual void getInfo( + cl_device_info param_name, + Binary& param) const = 0; + + /* TODO Delete dcl::Device::getId when all remote ICD objects are accessible through interface classes. */ + virtual object_id getId() const = 0; + /* TODO Delete dcl::Device::getComputeNode when all remote ICD objects are accessible through interface classes. */ + virtual ComputeNode& getComputeNode() const = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_DEVICE_H_ */ diff --git a/dclasio/include/dcl/Event.h b/dclasio/include/dcl/Event.h new file mode 100644 index 0000000..e03aa95 --- /dev/null +++ b/dclasio/include/dcl/Event.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.h + * + * \date 2012-07-28 + * \author Philipp Kegel + * + * dOpenCL event API + */ + +#ifndef DCL_EVENT_H_ +#define DCL_EVENT_H_ + +#include "CommandListener.h" +#include "SynchronizationListener.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dcl { + +/*! + * \brief Remote interface of an event + */ +class Event: virtual public CommandListener, virtual public SynchronizationListener { +public: + virtual ~Event() { } + + /*! + * \brief Returns profiling information for the command associated with event if profiling is enabled. + */ + virtual void getProfilingInfo( + cl_profiling_info param_name, + cl_ulong& param_value) const = 0; + +}; + +} /* namespace dcl */ + +#endif /* DCL_EVENT_H_ */ diff --git a/dclasio/include/dcl/Host.h b/dclasio/include/dcl/Host.h new file mode 100644 index 0000000..a52ec0d --- /dev/null +++ b/dclasio/include/dcl/Host.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Host.h + * + * \date 2011-08-07 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef DCL_HOST_H_ +#define DCL_HOST_H_ + +#include "Process.h" + +namespace dcl { + +/*! + * \brief A representation of a host running an OpenCL application. + * + * It is an interface between the dOpenCL communication layer and a + * daemon implementation. + */ +class Host: public virtual Process { +public: + virtual ~Host() { } +}; + +} /* namespace dcl */ + +#endif /* DCL_HOST_H_ */ diff --git a/dclasio/include/dcl/Kernel.h b/dclasio/include/dcl/Kernel.h new file mode 100644 index 0000000..020cff0 --- /dev/null +++ b/dclasio/include/dcl/Kernel.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Kernel.h + * + * \date 2012-08-05 + * \author Philipp Kegel + * + * dOpenCL kernel API + */ + +#ifndef DCL_KERNEL_H_ +#define DCL_KERNEL_H_ + +#include +#include + +namespace dcl { + +class Binary; +class Device; +class Memory; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface of a kernel. + */ +class Kernel { +public: + virtual ~Kernel() { } + + virtual void getInfo( + cl_kernel_info param_name, + Binary& param_value) const = 0; + virtual void getWorkGroupInfo( + const Device * device, + cl_kernel_work_group_info param_name, + Binary& param_value) const = 0; + + virtual void setArg( + cl_uint index, + const std::shared_ptr& memoryObject) = 0; + virtual void setArg( + cl_uint index, + size_t size, + const void *argPtr = nullptr) = 0; + +}; + +} /* namespace dcl */ + +#endif /* DCL_KERNEL_H_ */ diff --git a/dclasio/include/dcl/Memory.h b/dclasio/include/dcl/Memory.h new file mode 100644 index 0000000..da97d84 --- /dev/null +++ b/dclasio/include/dcl/Memory.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Memory.h + * + * \date 2012-08-05 + * \author Philipp Kegel + * + * dOpenCL memory object API + */ + +#ifndef DCL_MEMORY_H_ +#define DCL_MEMORY_H_ + +namespace dcl { + +/*! + * \brief Remote interface of a memory object. + * + * This is a tagging class only. + */ +class Memory { +public: + virtual ~Memory() { } + +}; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface of a buffer. + * + * This is a tagging class only. + */ +class Buffer: virtual public Memory { +public: + ~Buffer() { } + +}; + +} /* namespace dcl */ + +#endif /* DCL_MEMORY_H_ */ diff --git a/dclasio/include/dcl/Process.h b/dclasio/include/dcl/Process.h new file mode 100644 index 0000000..dc9b9d5 --- /dev/null +++ b/dclasio/include/dcl/Process.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Process.h + * + * \date 2011-08-07 + * \author Philipp Kegel + * + * C++ API declarations for dOpenCL communication layer + */ + +#ifndef DCL_PROCESS_H_ +#define DCL_PROCESS_H_ + +/* TODO Remove message headers from process interface */ +#include + +#include + +#include +#include +#include + +namespace dcl { + +class DataTransfer; + +/* ****************************************************************************/ + +/*! + * \brief A generalization of a node in a dOpenCL network. + * + * A process can represent a host or a compute node. + */ +class Process { +public: + virtual ~Process() { } + + virtual const std::string& url() const = 0; + + /*! + * \brief Sends a message to this process + * \param[in] message the message to send + * + * \deprecated Messages are not part of the dOpenCL API and must not be send by the application layer directly + */ + virtual void sendMessage( + const dclasio::message::Message& message) const = 0; + + /*! + * \brief Send data to process. + * This is a non-blocking operation. + * + * \param[in] size size of data buffer + * \param[in] ptr data buffer + * \return + */ + virtual std::shared_ptr sendData( + size_t size, + const void *ptr) = 0; + + /*! + * \brief Receive data from host. + * This is a non-blocking operation. + * + * \param[in] size size of data buffer + * \param[out] ptr data buffer + * \return + */ + virtual std::shared_ptr receiveData( + size_t size, + void * ptr) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_PROCESS_H_ */ diff --git a/dclasio/include/dcl/Program.h b/dclasio/include/dcl/Program.h new file mode 100644 index 0000000..964e719 --- /dev/null +++ b/dclasio/include/dcl/Program.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Program.h + * + * \date 2012-08-05 + * \author Philipp Kegel + * + * dOpenCL program API + */ + +#ifndef DCL_PROGRAM_H_ +#define DCL_PROGRAM_H_ + +#include +#include + +namespace dcl { + +class Device; +class Kernel; +class ProgramBuildListener; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface of a program. + */ +class Program { +public: + virtual ~Program() { } + + /* TODO Pass program build listener by raw pointer or reference */ + /*! + * \brief Build a program + * + * \param[in] deviceList the devices to build the program for + * \param[in] options build options + * \param[in] programBuildListener a proxy for a remote program build listener + */ + virtual void build( + const std::vector& deviceList, + const char * options, + const std::shared_ptr& programBuildListener) = 0; + + virtual void createKernels( + std::vector>& kernels) = 0; + +}; + +} /* namespace dcl */ + +#endif /* DCL_PROGRAM_H_ */ diff --git a/dclasio/include/dcl/ProgramBuildListener.h b/dclasio/include/dcl/ProgramBuildListener.h new file mode 100644 index 0000000..a2d4e61 --- /dev/null +++ b/dclasio/include/dcl/ProgramBuildListener.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProgramBuildListener.h + * + * \date 2012-07-07 + * \author Philipp Kegel + * + * dOpenCL program API + */ + +#ifndef DCL_PROGRAMBUILDLISTENER_H_ +#define DCL_PROGRAMBUILDLISTENER_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dcl { + +class Device; + +/* ****************************************************************************/ + +/*! + * \brief Remote interface of a program build listener + */ +class ProgramBuildListener { +public: + virtual ~ProgramBuildListener() { } + + /*! + * \brief Callback for program build completion. + * + * \param[in] devices devices for which the program has been built + * \param[in] buildStatus build statuses for devices + */ + virtual void onComplete( + const std::vector& devices, + const std::vector& buildStatus) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_PROGRAMBUILDLISTENER_H_ */ diff --git a/dclasio/include/dcl/Remote.h b/dclasio/include/dcl/Remote.h new file mode 100644 index 0000000..5d2140f --- /dev/null +++ b/dclasio/include/dcl/Remote.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Remote.h + * + * \date 2011-04-12 + * \author Philipp Kegel + */ + +#ifndef REMOTE_H_ +#define REMOTE_H_ + +#include "DCLTypes.h" + +namespace dcl { + +/*! + * \brief A base class for remote objects + */ +class Remote { +public: + static object_id generateId(); + + + object_id remoteId() const; + +protected: + Remote(); + Remote( + object_id id); + ~Remote(); + + /*! + * \brief A (unique) object ID. + * + * Virtually each object in dOpenCL is assigned a unique ID for identifying + * the object across a network. + * + * The ID 0 is reserved to identify \c NULL pointers or 'missing' objects. + * Hence, this ID must not be associated with any object. + */ + /* TODO Use UUIDs to ensure globally unique ID */ + const object_id _id; + +private: + static object_id objectCount; +}; + +} /* namespace dcl */ + +#endif /* REMOTE_H_ */ diff --git a/dclasio/include/dcl/Session.h b/dclasio/include/dcl/Session.h new file mode 100644 index 0000000..e928ab3 --- /dev/null +++ b/dclasio/include/dcl/Session.h @@ -0,0 +1,215 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Session.h + * + * \date 2013-09-29 + * \author Philipp Kegel + */ + +#ifndef DCL_SESSION_H_ +#define DCL_SESSION_H_ + +#include "DCLTypes.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dcl { + +class Buffer; +class CommandQueue; +class ComputeNode; +class Context; +class ContextListener; +class Device; +class Event; +class Host; +class Kernel; +class Memory; +class Program; +class UserEvent; + +/* ****************************************************************************/ + +/*! + * \brief An interface for an application session + * + * An application session holds ownership of all OpenCL application objects. + * It is a factory for these objects. + */ +class Session { +public: + virtual ~Session() { } + + /*! + * \brief Creates a context for this session + */ + virtual std::shared_ptr createContext( + Host& host, + const std::vector& computeNodes, + const std::vector& devices, + const std::shared_ptr& listener) = 0; + + /*! + * \brief Deletes a context from this session + * + * \param[in] context the context to delete + */ + virtual void releaseContext( + const std::shared_ptr& context) = 0; + + /*! + * \brief Creates a command queue for this session + */ + virtual std::shared_ptr createCommandQueue( + const std::shared_ptr& context, + Device * device, + cl_command_queue_properties properties) = 0; + + /*! + * \brief Deletes a command queue from this session + * + * \param[in] commandQueue the command queue to delete + */ + virtual void releaseCommandQueue( + const std::shared_ptr& commandQueue) = 0; + + /*! + * \brief Creates a buffer for this session + */ + virtual std::shared_ptr createBuffer( + const std::shared_ptr& context, + cl_mem_flags flags, + size_t size, + void * ptr) = 0; + + /*! + * \brief Deletes a memory object (buffer or image) from this session. + * + * \param[in] memory the memory object to delete + */ + virtual void releaseMemObject( + const std::shared_ptr& memory) = 0; + + /*! + * \brief Creates a program for this session from source + */ + virtual std::shared_ptr createProgram( + const std::shared_ptr& context, + const char * source, + size_t length) = 0; + + /*! + * \brief Creates a program for this session from binary + */ + virtual std::shared_ptr createProgram( + const std::shared_ptr& context, + const std::vector& deviceList, + const std::vector& lengths, + const unsigned char ** binaries, + std::vector * binary_status) = 0; + + /*! + * \brief Deletes a program from this session. + * + * \param[in] program the program to delete + */ + virtual void releaseProgram( + const std::shared_ptr& program) = 0; + + /*! + * \brief Creates a kernel for this session + */ + virtual std::shared_ptr createKernel( + const std::shared_ptr& program, + const char * name) = 0; + + /*! + * \brief Creates all kernels of a program for this session + * + * \param[in] program the program which kernels should be created + * \param[in] numKernels expected number of kernels in program + * If \c program contains more or less than \c numKernels, \c CL_INVALID_VALUE is thrown + * \return all kernels in \c program + */ + virtual std::vector> createKernelsInProgram( + const std::shared_ptr& program, + cl_uint numKernels) = 0; + + /*! + * \brief Deletes a kernel from this session. + * + * \param[in] kernel the kernel to delete + */ + virtual void releaseKernel( + const std::shared_ptr& kernel) = 0; + + virtual void addEvent( + const std::shared_ptr& event) = 0; + + /*! + * \brief Creates a replacement event (remote or user event) and adds it to the session's event list + * + * \param[in] id command ID + * \param[in] context the context associated with the event + * \param[in] memoryObjects the memory objects associated with the event + */ + virtual std::shared_ptr createEvent( + object_id id, + const std::shared_ptr& context, + const std::vector>& memoryObjects) = 0; + + /*! + * \brief Deletes an event from this session. + * + * \param[in] event the event to delete + */ + virtual void releaseEvent( + const std::shared_ptr& event) = 0; +}; + +} /* namespace dcl */ + +#endif /* DCL_SESSION_H_ */ diff --git a/dclasio/include/dcl/SynchronizationListener.h b/dclasio/include/dcl/SynchronizationListener.h new file mode 100644 index 0000000..b33e484 --- /dev/null +++ b/dclasio/include/dcl/SynchronizationListener.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file SynchronizationListener.h + * + * \date 2013-01-30 + * \author Philipp Kegel + * \author Sebastian Pribnow + */ + +#ifndef DCL_SYNCHRONIZATIONLISTENER_H_ +#define DCL_SYNCHRONIZATIONLISTENER_H_ + +namespace dcl { + +class Process; + +/* ****************************************************************************/ + +/*! + * \brief A listener API for synchronization request + * + * A synchronization listener is informed when a process requests a synchronization. + * This API is implemented by events in the dOpenCL ICD and daemon in order to perform memory updates. + */ +class SynchronizationListener { +public: + virtual ~SynchronizationListener() { } + + /*! + * \brief Synchronizes (releases) the changes associated with this event wrapper's native event + * + * Summarizes two scenarios: + * - a compute node has to synchronize its memory object because of a found + * event listener and performs an acquire operation. In this case, + * onAcquire is called on the host to answer the request of the compute + * node. This is necessary, since the compute nodes can't communicate + * among each other at the moment. \c process then is the requesting + * compute node. + * If available, the host sends the updated copy of the requested memory + * object to the requesting compute node. Otherwise, the host performs an + * acquire operation on the compute node being the owner of the event. + * This leads to the second case: + * - onAcquire is called on a compute node, triggered by an acquire + * operation on the host. In this case, \c process is the host and the + * compute node's copies of all memory objects associated with the event + * are sent to the host. + * + * \param[in] process the process (host or compute node) that requested the synchronization + */ + virtual void onSynchronize( + Process& process) = 0; + +}; + +} /* namespace dcl */ + +#endif /* DCL_SYNCHRONIZATIONLISTENER_H_ */ diff --git a/dclasio/include/dcl/dcl.dox b/dclasio/include/dcl/dcl.dox new file mode 100644 index 0000000..817d723 --- /dev/null +++ b/dclasio/include/dcl/dcl.dox @@ -0,0 +1,11 @@ +/*! + * \namespace dcl + * \brief C++ API declarations for the dOpenCL communication layer + * + * dOpenCL specifies a communication API that is implementation by dOpenCL + * communication libraries. This API decouples the dOpenCL ICD and daemon from + * the particular communication API (e.g., sockets, Boost.Asio) that is used to + * implement the communication layer. + */ + + \ No newline at end of file diff --git a/dclasio/include/dcl/util/Clock.h b/dclasio/include/dcl/util/Clock.h new file mode 100644 index 0000000..3fb6747 --- /dev/null +++ b/dclasio/include/dcl/util/Clock.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Clock.h + * + * \date 2013-02-27 + * \author Philipp Kegel + */ + +#ifndef CLOCK_H_ +#define CLOCK_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dcl { + +namespace util { + +/*! + * \brief A simple class for creating OpenCL-like time stamps from a global clock + * + * This clock should return monotonic time stamps which are valid on all nodes + * of a distributed system used by dOpenCL. Thus, time stamps from different + * nodes are comparable to each other, in order to, e.g., profile runtime of + * commands or data transfers. + */ +class Clock { +public: + Clock(); + virtual ~Clock(); + + /*! + * \brief Returns the number of elapsed nanoseconds since an arbitrary but fixed time point. + * + * \return a time point + */ + cl_ulong getTime(); + +private: + /*! + * \brief Synchronizes this clock with a global clock + * + * This methods computes the clock skew of the system clock and a global + * clock. + */ + void sync(); + + cl_ulong _clockSkew; //!< clock skew in nanoseconds + std::chrono::time_point _start; //!< fixed time point to compute differences with +}; + +/* ****************************************************************************/ + +extern Clock clock; + +} // namespace util + +} // namespace dcl + +#endif /* CLOCK_H_ */ diff --git a/dclasio/include/dcl/util/Logger.h b/dclasio/include/dcl/util/Logger.h new file mode 100644 index 0000000..74519a3 --- /dev/null +++ b/dclasio/include/dcl/util/Logger.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Logger.h + * + * \date 2011-08-08 + * \author Michel Steuwer + * \author Philipp Kegel + */ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include +#include + +namespace dcl { + +namespace util { + +enum class Severity { + Error = 1, + Warning = 2, + Info = 3, + Debug = 4, + Verbose = 5 +}; + +/*! + * \brief A simple logger + */ +class LoggerImpl: public std::ostream { +public: + LoggerImpl(); + + void setOutput(std::ostream& output); + + void setLoggingLevel(Severity severity); + + void setDefaultSeverity(Severity severity); + + /*! + * \brief Sets logging level until next flush + */ + void setCurrentSeverity(Severity severity); + +private: + std::string severityToString(Severity severity); + + class LoggerBuffer: public std::stringbuf { + public: + LoggerBuffer(LoggerImpl& logger, std::ostream& stream); + + void setOutput(std::ostream& output); + + virtual int sync(); + private: + LoggerImpl &_logger; + std::ostream *_output; + std::mutex _mutex; //!< Mutex to synchronize logging + }; + + Severity _currentSeverity; + Severity _defaultSeverity; + Severity _maxSeverity; + LoggerBuffer _buffer; +}; + +/* + * custom manipulators + */ + +LoggerImpl& operator<<( + LoggerImpl& logger, + LoggerImpl& (*manipulator)(LoggerImpl&)); + +LoggerImpl& Error(LoggerImpl& logger); + +LoggerImpl& Warning(LoggerImpl& logger); + +LoggerImpl& Info(LoggerImpl& logger); + +LoggerImpl& Debug(LoggerImpl& logger); + +LoggerImpl& Verbose(LoggerImpl& logger); + +extern LoggerImpl Logger; + +} // namespace util + +} // namespace dcl + +#endif // LOGGER_H_ diff --git a/dclasio/include/dcl/util/README.txt b/dclasio/include/dcl/util/README.txt new file mode 100644 index 0000000..a36faa9 --- /dev/null +++ b/dclasio/include/dcl/util/README.txt @@ -0,0 +1 @@ +The utility classes have been taken from the PVS library. \ No newline at end of file diff --git a/dclasio/include/dclasio/message/BuildProgram.h b/dclasio/include/dclasio/message/BuildProgram.h new file mode 100644 index 0000000..28fc86f --- /dev/null +++ b/dclasio/include/dclasio/message/BuildProgram.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file BuildProgram.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef BUILDPROGRAM_H_ +#define BUILDPROGRAM_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class BuildProgram: public Request { +public: + BuildProgram(); + BuildProgram( + dcl::object_id programId, + const std::vector& deviceIds, + const std::string& options, + dcl::object_id programBuildId); + BuildProgram( + const BuildProgram& rhs); + + dcl::object_id programId() const; + const std::vector& deviceIds() const; + const std::string& options() const; + dcl::object_id programBuildId() const; + + static const class_type TYPE = 100 + BUILD_PROGRAM; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _programId << _deviceIds << _options << _programBuildId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _programId >> _deviceIds >> _options >> _programBuildId; + } + +private: + dcl::object_id _programId; + std::vector _deviceIds; + std::string _options; + dcl::object_id _programBuildId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* BUILDPROGRAM_H_ */ diff --git a/dclasio/include/dclasio/message/CommandMessage.h b/dclasio/include/dclasio/message/CommandMessage.h new file mode 100644 index 0000000..dfb9e98 --- /dev/null +++ b/dclasio/include/dclasio/message/CommandMessage.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandMessage.h + * + * Command related messages + * + * \date 2011-07-11 + * \author Philipp Kegel + */ + +#ifndef COMMAND_MESSAGE_H_ +#define COMMAND_MESSAGE_H_ + +#include "Message.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +namespace message { + +/*! + * \brief Notification of command execution status changes. + * + * This message is sent from compute nodes to the host. + */ +class CommandExecutionStatusChangedMessage: public Message { +public: + CommandExecutionStatusChangedMessage(); + CommandExecutionStatusChangedMessage( + dcl::object_id commandId, + cl_int status); + CommandExecutionStatusChangedMessage( + const CommandExecutionStatusChangedMessage& rhs); + virtual ~CommandExecutionStatusChangedMessage(); + + dcl::object_id commandId() const; + cl_int status() const; + + static const class_type TYPE = 601; + + Message::class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + buf << _commandId << _status; + } + + void unpack(dcl::ByteBuffer& buf) { + buf >> _commandId >> _status; + } + + +private: + dcl::object_id _commandId; + cl_int _status; +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* COMMAND_MESSAGE_H_ */ diff --git a/dclasio/include/dclasio/message/CreateBuffer.h b/dclasio/include/dclasio/message/CreateBuffer.h new file mode 100644 index 0000000..f02b566 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateBuffer.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATEBUFFER_H_ +#define CREATEBUFFER_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { +namespace message { + +class CreateBuffer : public Request { +public: + CreateBuffer(); + CreateBuffer( + dcl::object_id bufferId, + dcl::object_id contextId, + cl_mem_flags flags, + size_t size); + CreateBuffer( + const CreateBuffer& rhs); + + dcl::object_id bufferId() const; + dcl::object_id contextId() const; + cl_mem_flags flags() const; + size_t size() const; + + static const class_type TYPE = 100 + CREATE_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _bufferId << _contextId << _flags << _size; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _bufferId >> _contextId >> _flags >> _size; + } + +private: + dcl::object_id _bufferId; + dcl::object_id _contextId; + cl_mem_flags _flags; + size_t _size; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATEBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/CreateCommandQueue.h b/dclasio/include/dclasio/message/CreateCommandQueue.h new file mode 100644 index 0000000..150fae3 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateCommandQueue.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file CreateCommandQueue.h + * + * @date 2011-05-31 + * @author Tunc Taylan Turunc + */ + +#ifndef CREATECOMMANDQUEUE_H_ +#define CREATECOMMANDQUEUE_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +namespace message { + +class CreateCommandQueue: public Request { +public: + CreateCommandQueue(); + CreateCommandQueue( + dcl::object_id contextId, + dcl::object_id deviceId, + dcl::object_id commandQueueId, + cl_command_queue_properties properties); + CreateCommandQueue( + const CreateCommandQueue& rhs); + + dcl::object_id contextId() const; + dcl::object_id deviceId() const; + dcl::object_id commandQueueId() const; + cl_command_queue_properties properties() const; + + static const class_type TYPE = 100 + CREATE_COMMAND_QUEUE; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _contextId << _deviceId << _commandQueueId << _properties; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _contextId >> _deviceId >> _commandQueueId >> _properties; + } + +private: + dcl::object_id _contextId; + dcl::object_id _deviceId; + dcl::object_id _commandQueueId; + cl_command_queue_properties _properties; +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* CREATECOMMANDQUEUE_H_ */ diff --git a/dclasio/include/dclasio/message/CreateContext.h b/dclasio/include/dclasio/message/CreateContext.h new file mode 100644 index 0000000..b828759 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateContext.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateContext.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATECONTEXT_H_ +#define CREATECONTEXT_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { +namespace message { + +/* TODO Decide on how to specify compute nodes + * 1) compute nodes are dynamically created on each other when they should + * interact in a context. In this case URLs or other identifiers have to be + * transmitted. + * 2) compute nodes should be created on each other as soon as they are created + * on the host. In this case compute nodes can be identified by their ID + * within dOpenCL. + */ +class CreateContext: public Request { +public: + CreateContext(); + CreateContext( + dcl::object_id contextId, + const std::vector& computeNodeIds); + CreateContext( + dcl::object_id contextId, + const std::vector& computeNodeIds, + cl_device_type deviceType); + CreateContext( + dcl::object_id contextId, + const std::vector& computeNodeIds, + const std::vector& deviceIds); + CreateContext( + const CreateContext& rhs); + + dcl::object_id contextId() const; + const std::vector& computeNodeIds() const; + cl_device_type deviceType() const; + const std::vector& deviceIds() const; + + static const class_type TYPE = 100 + CREATE_CONTEXT; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _contextId << _computeNodeIds << _deviceType << _deviceIds; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _contextId >> _computeNodeIds >> _deviceType >> _deviceIds; + } + +private: + dcl::object_id _contextId; + std::vector _computeNodeIds; + //! Only select devices of the specified types(s) for the context + cl_device_type _deviceType; + //! Only select the specified devices for the context, or all devices if no devices are specified + std::vector _deviceIds; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATECONTEXT_H_ */ diff --git a/dclasio/include/dclasio/message/CreateEvent.h b/dclasio/include/dclasio/message/CreateEvent.h new file mode 100644 index 0000000..2a322b3 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateEvent.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateEvent.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATEEVENT_H_ +#define CREATEEVENT_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { + +namespace message { + +/*! + * \brief A request message for creating an event. + */ +class CreateEvent: public Request { +public: + CreateEvent(); + CreateEvent( + dcl::object_id contextId, + dcl::object_id eventId, + const std::vector& memObjectIds); + CreateEvent( + const CreateEvent& rhs); + virtual ~CreateEvent(); + + dcl::object_id contextId() const; + dcl::object_id eventId() const; + const std::vector& memObjectIds() const; + + static const class_type TYPE = 100 + CREATE_EVENT; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _contextId << _eventId << _memObjectIds; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _contextId >> _eventId >> _memObjectIds; + } + +private: + dcl::object_id _contextId; + dcl::object_id _eventId; + std::vector _memObjectIds; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATEEVENT_H_ */ diff --git a/dclasio/include/dclasio/message/CreateKernel.h b/dclasio/include/dclasio/message/CreateKernel.h new file mode 100644 index 0000000..ee4ed85 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateKernel.h @@ -0,0 +1,96 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateKernel.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATEKERNEL_H_ +#define CREATEKERNEL_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { + +namespace message { + +class CreateKernel: public Request { +public: + CreateKernel(); + CreateKernel( + dcl::object_id kernelId, + dcl::object_id programId, + const char * kernelName); + CreateKernel(const CreateKernel& rhs); + + dcl::object_id kernelId() const; + dcl::object_id programId() const; + const char * kernelName() const; + + static const class_type TYPE = 100 + CREATE_KERNEL; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _kernelId << _programId << _kernelName; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _kernelId >> _programId >> _kernelName; + } + +private: + dcl::object_id _kernelId; + dcl::object_id _programId; + std::string _kernelName; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATEKERNEL_H_ */ diff --git a/dclasio/include/dclasio/message/CreateKernelsInProgram.h b/dclasio/include/dclasio/message/CreateKernelsInProgram.h new file mode 100644 index 0000000..67be610 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateKernelsInProgram.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateKernelsInProgram.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATEKERNELSINPROGRAM_H_ +#define CREATEKERNELSINPROGRAM_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { + +namespace message { + +class CreateKernelsInProgram: public Request { +public: + CreateKernelsInProgram(); + CreateKernelsInProgram( + dcl::object_id programId, + const std::vector& kernelIds); + CreateKernelsInProgram( + const CreateKernelsInProgram& rhs); + + const std::vector& kernelIds() const; + dcl::object_id programId() const; + + static const class_type TYPE = 100 + CREATE_KERNELS_IN_PROGRAM; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _programId << _kernelIds; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _programId >> _kernelIds; + } + +private: + dcl::object_id _programId; + std::vector _kernelIds; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATEKERNELSINPROGRAM_H_ */ diff --git a/dclasio/include/dclasio/message/CreateProgramWithBinary.h b/dclasio/include/dclasio/message/CreateProgramWithBinary.h new file mode 100644 index 0000000..45be658 --- /dev/null +++ b/dclasio/include/dclasio/message/CreateProgramWithBinary.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateProgramWithBinary.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATEPROGRAMWITHBINARY_H_ +#define CREATEPROGRAMWITHBINARY_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class CreateProgramWithBinary: public Request { +public: + CreateProgramWithBinary( + const dcl::object_id programId, + const dcl::object_id contextId, + const std::vector& deviceIds, + const std::vector& lengths); + CreateProgramWithBinary( + const CreateProgramWithBinary& rhs); + virtual ~CreateProgramWithBinary(); + + dcl::object_id programId() const; + dcl::object_id contextId() const; + const std::vector& deviceIds() const; + const std::vector& lengths() const; + + static const class_type TYPE = 100 + CREATE_PROGRAM_WITH_BINARY; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _programId << _contextId << _deviceIds << _lengths; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _programId >> _contextId >> _deviceIds >> _lengths; + } + +private: + dcl::object_id _programId; + dcl::object_id _contextId; + std::vector _deviceIds; + std::vector _lengths; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATEPROGRAMWITHBINARY_H_ */ diff --git a/dclasio/include/dclasio/message/CreateProgramWithSource.h b/dclasio/include/dclasio/message/CreateProgramWithSource.h new file mode 100644 index 0000000..7e6268c --- /dev/null +++ b/dclasio/include/dclasio/message/CreateProgramWithSource.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateProgramWithSource.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef CREATEPROGRAMWITHSOURCE_H_ +#define CREATEPROGRAMWITHSOURCE_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { +namespace message { + +class CreateProgramWithSource: public Request { +public: + CreateProgramWithSource(); + CreateProgramWithSource( + const dcl::object_id program_id, + const dcl::object_id context_id, + const size_t length); + CreateProgramWithSource( + const CreateProgramWithSource& rhs); + virtual ~CreateProgramWithSource(); + + dcl::object_id programId() const; + dcl::object_id contextId() const; + size_t length() const; + + static const class_type TYPE = 100 + CREATE_PROGRAM_WITH_SOURCE; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _programId << _contextId << _length; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _programId >> _contextId >> _length; + } + +private: + dcl::object_id _programId; + dcl::object_id _contextId; + size_t _length; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* CREATEPROGRAMWITHSOURCE_H_ */ diff --git a/dclasio/include/dclasio/message/DeleteCommandQueue.h b/dclasio/include/dclasio/message/DeleteCommandQueue.h new file mode 100644 index 0000000..0ff2a94 --- /dev/null +++ b/dclasio/include/dclasio/message/DeleteCommandQueue.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteCommandQueue.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef DELETECOMMANDQUEUE_H_ +#define DELETECOMMANDQUEUE_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +class DeleteCommandQueue: public Request { +public: + DeleteCommandQueue(); + DeleteCommandQueue( + dcl::object_id commandQueueId); + DeleteCommandQueue( + const DeleteCommandQueue& rhs); + virtual ~DeleteCommandQueue(); + + dcl::object_id commandQueueId() const; + + static const class_type TYPE = 100 + RELEASE_COMMAND_QUEUE; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId; + } + +private: + dcl::object_id _commandQueueId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* DELETECOMMANDQUEUE_H_ */ diff --git a/dclasio/include/dclasio/message/DeleteContext.h b/dclasio/include/dclasio/message/DeleteContext.h new file mode 100644 index 0000000..b92a000 --- /dev/null +++ b/dclasio/include/dclasio/message/DeleteContext.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteContext.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef DELETECONTEXT_H_ +#define DELETECONTEXT_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +class DeleteContext: public Request { +public: + DeleteContext(); + DeleteContext( + dcl::object_id contextId); + DeleteContext( + const DeleteContext& rhs); + virtual ~DeleteContext(); + + dcl::object_id contextId() const; + + static const class_type TYPE = 100 + RELEASE_CONTEXT; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _contextId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _contextId; + } + +private: + dcl::object_id _contextId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* DELETECONTEXT_H_ */ diff --git a/dclasio/include/dclasio/message/DeleteEvent.h b/dclasio/include/dclasio/message/DeleteEvent.h new file mode 100644 index 0000000..366df1a --- /dev/null +++ b/dclasio/include/dclasio/message/DeleteEvent.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteEvent.h + * + * \date 2011-07-11 + * \author Philipp Kegel + */ + +#ifndef DELETEEVENT_H_ +#define DELETEEVENT_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { + +namespace message { + +/*! + * \brief A request message for deleting an event. + */ +class DeleteEvent: public Request { +public: + DeleteEvent(); + DeleteEvent( + dcl::object_id eventId); + DeleteEvent( + const DeleteEvent& rhs); + virtual ~DeleteEvent(); + + dcl::object_id eventId() const; + + static const class_type TYPE = 100 + RELEASE_EVENT; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _eventId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _eventId; + } + +private: + dcl::object_id _eventId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* DELETEEVENT_H_ */ diff --git a/dclasio/include/dclasio/message/DeleteKernel.h b/dclasio/include/dclasio/message/DeleteKernel.h new file mode 100644 index 0000000..2f23dfe --- /dev/null +++ b/dclasio/include/dclasio/message/DeleteKernel.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteKernel.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef DELETEKERNEL_H_ +#define DELETEKERNEL_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { + +namespace message { + +class DeleteKernel: public Request { +public: + DeleteKernel(); + DeleteKernel( + dcl::object_id kernelId); + DeleteKernel( + const DeleteKernel& rhs); + virtual ~DeleteKernel(); + + dcl::object_id kernelId() const; + + static const class_type TYPE = 100 + RELEASE_KERNEL; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _kernelId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _kernelId; + } + +private: + dcl::object_id _kernelId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* DELETEKERNEL_H_ */ diff --git a/dclasio/include/dclasio/message/DeleteMemory.h b/dclasio/include/dclasio/message/DeleteMemory.h new file mode 100644 index 0000000..d8af8dd --- /dev/null +++ b/dclasio/include/dclasio/message/DeleteMemory.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteMemory.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef DELETEMEMORY_H_ +#define DELETEMEMORY_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +class DeleteMemory: public Request { +public: + DeleteMemory(); + DeleteMemory( + dcl::object_id memObjectId); + DeleteMemory( + const DeleteMemory& rhs); + virtual ~DeleteMemory(); + + dcl::object_id memObjectId() const; + + static const class_type TYPE = 100 + RELEASE_MEM_OBJECT; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _memObjectId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _memObjectId; + } + +private: + dcl::object_id _memObjectId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* DELETEMEMORY_H_ */ diff --git a/dclasio/include/dclasio/message/DeleteProgram.h b/dclasio/include/dclasio/message/DeleteProgram.h new file mode 100644 index 0000000..218a58e --- /dev/null +++ b/dclasio/include/dclasio/message/DeleteProgram.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteProgram.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef DELETEPROGRAM_H_ +#define DELETEPROGRAM_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +class DeleteProgram: public Request { +public: + DeleteProgram(); + DeleteProgram( + dcl::object_id programId); + DeleteProgram( + const DeleteProgram& rhs); + virtual ~DeleteProgram(); + + dcl::object_id programId() const; + + static const class_type TYPE = 100 + RELEASE_PROGRAM; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _programId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _programId; + } + +private: + dcl::object_id _programId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* DELETEPROGRAM_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueBarrier.h b/dclasio/include/dclasio/message/EnqueueBarrier.h new file mode 100644 index 0000000..a9dfd42 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueBarrier.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueBarrier.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEBARRIER_H_ +#define ENQUEUEBARRIER_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { +namespace message { + +class EnqueueBarrier: public Request { +public: + EnqueueBarrier(); + EnqueueBarrier( + dcl::object_id commandQueueId, + dcl::object_id commandId, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueBarrier(const EnqueueBarrier& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_BARRIER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEBARRIER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueBroadcastBuffer.h b/dclasio/include/dclasio/message/EnqueueBroadcastBuffer.h new file mode 100644 index 0000000..3ee3394 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueBroadcastBuffer.h @@ -0,0 +1,117 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueBroadcastBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEBROADCASTBUFFER_H_ +#define ENQUEUEBROADCASTBUFFER_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueBroadcastBuffer : public Request { +public: + EnqueueBroadcastBuffer(); + EnqueueBroadcastBuffer( + const std::vector& commandQueueIds, + dcl::object_id commandId, + dcl::object_id srcBufferId, + const std::vector& dstBufferIds, + size_t srcOffset, + const std::vector& dstOffsets, + size_t cb, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueBroadcastBuffer( + const EnqueueBroadcastBuffer& rhs); + + const std::vector& commandQueueIds() const; + dcl::object_id commandId() const; + dcl::object_id srcBufferId() const; + const std::vector& dstBufferIds() const; + size_t srcOffset() const; + const std::vector& dstOffsets() const; + size_t cb() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_BROADCAST_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueIds << _commandId << _srcBufferId << _dstBufferIds + << _srcOffset << _dstOffsets << _cb << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueIds >> _commandId >> _srcBufferId >> _dstBufferIds + >> _srcOffset >> _dstOffsets >> _cb >> _eventIdWaitList >> _event; + } + +private: + std::vector _commandQueueIds; + dcl::object_id _commandId; + dcl::object_id _srcBufferId; + std::vector _dstBufferIds; + size_t _srcOffset; + std::vector _dstOffsets; + size_t _cb; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEBROADCASTBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueCopyBuffer.h b/dclasio/include/dclasio/message/EnqueueCopyBuffer.h new file mode 100644 index 0000000..8750789 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueCopyBuffer.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueCopyBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUECOPYBUFFER_H_ +#define ENQUEUECOPYBUFFER_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueCopyBuffer : public Request{ +public: + EnqueueCopyBuffer(); + EnqueueCopyBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id srcBufferId, + dcl::object_id dstBufferId, + size_t srcOffset, + size_t dstOffset, + size_t cb, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueCopyBuffer( + const EnqueueCopyBuffer& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + dcl::object_id srcBufferId() const; + dcl::object_id dstBufferId() const; + size_t srcOffset() const; + size_t dstOffset() const; + size_t cb() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_COPY_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _srcBufferId << _dstBufferId + << _srcOffset << _dstOffset << _cb << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _srcBufferId >> _dstBufferId + >> _srcOffset >> _dstOffset >> _cb >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + dcl::object_id _srcBufferId; + dcl::object_id _dstBufferId; + size_t _srcOffset; + size_t _dstOffset; + size_t _cb; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* ENQUEUECOPYBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueMapBuffer.h b/dclasio/include/dclasio/message/EnqueueMapBuffer.h new file mode 100644 index 0000000..2f92696 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueMapBuffer.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueMapBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEMAPBUFFER_H_ +#define ENQUEUEMAPBUFFER_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueMapBuffer: public Request { +public: + EnqueueMapBuffer(); + EnqueueMapBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + bool blocking_map, + cl_map_flags map_flags, + size_t offset, + size_t cb, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueMapBuffer(const EnqueueMapBuffer& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + dcl::object_id bufferId() const; + bool blocking() const; + cl_map_flags mapFlags() const; + size_t offset() const; + size_t cb() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_MAP_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _bufferId << _blocking + << _mapFlags << _offset << _cb << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _bufferId >> _blocking + >> _mapFlags >> _offset >> _cb >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + dcl::object_id _bufferId; + bool _blocking; + cl_map_flags _mapFlags; + size_t _offset; + size_t _cb; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEMAPBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueMarker.h b/dclasio/include/dclasio/message/EnqueueMarker.h new file mode 100644 index 0000000..11d4916 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueMarker.h @@ -0,0 +1,99 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueMarker.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEMARKER_H_ +#define ENQUEUEMARKER_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { +namespace message { + +class EnqueueMarker: public Request { +public: + EnqueueMarker(); + EnqueueMarker( + dcl::object_id commandQueueId, + dcl::object_id commandId, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueMarker( + const EnqueueMarker& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_MARKER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEMARKER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueNDRangeKernel.h b/dclasio/include/dclasio/message/EnqueueNDRangeKernel.h new file mode 100644 index 0000000..68ab3af --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueNDRangeKernel.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueNDRangeKernel.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUENDRANGEKERNEL_H_ +#define ENQUEUENDRANGEKERNEL_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueNDRangeKernel: public Request { +public: + EnqueueNDRangeKernel(); + EnqueueNDRangeKernel( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id kernelId, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueNDRangeKernel(const EnqueueNDRangeKernel& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + dcl::object_id kernelId() const; + + const std::vector& offset() const; + const std::vector& global() const; + const std::vector& local() const; + + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_NDRANGE_KERNEL; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _kernelId << _offset << _global + << _local << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _kernelId >> _offset >> _global + >> _local >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + dcl::object_id _kernelId; + std::vector _offset; + std::vector _global; + std::vector _local; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUENDRANGEKERNEL_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueReadBuffer.h b/dclasio/include/dclasio/message/EnqueueReadBuffer.h new file mode 100644 index 0000000..b68513c --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueReadBuffer.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueReadBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEREADBUFFER_H_ +#define ENQUEUEREADBUFFER_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueReadBuffer : public Request { +public: + EnqueueReadBuffer(); + EnqueueReadBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + bool blocking_read, + size_t offset, + size_t cb, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueReadBuffer( + const EnqueueReadBuffer& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + dcl::object_id bufferId() const; + bool blocking() const; + size_t offset() const; + size_t cb() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_READ_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _bufferId << _blocking << _offset << _cb << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _bufferId >> _blocking >> _offset >> _cb >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + dcl::object_id _bufferId; + bool _blocking; + size_t _offset; + size_t _cb; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEREADBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueReduceBuffer.h b/dclasio/include/dclasio/message/EnqueueReduceBuffer.h new file mode 100644 index 0000000..55e8403 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueReduceBuffer.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueReduceBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEREDUCEBUFFER_H_ +#define ENQUEUEREDUCEBUFFER_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueReduceBuffer : public Request { +public: + EnqueueReduceBuffer(); + EnqueueReduceBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + const std::vector& srcIds, + dcl::object_id dstId, + dcl::object_id kernelId, + const std::vector& offset, + const std::vector& lobal, + const std::vector& local, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueReduceBuffer( + const EnqueueReduceBuffer& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + const std::vector& srcIds() const; + dcl::object_id dstId() const; + dcl::object_id kernelId() const; + + const std::vector& offset() const; + const std::vector& global() const; + const std::vector& local() const; + + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_REDUCE_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _srcIds << _dstId << _kernelId + << _offset << _global << _local << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _srcIds >> _dstId >> _kernelId + >> _offset >> _global >> _local >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + std::vector _srcIds; + dcl::object_id _dstId; + dcl::object_id _kernelId; + std::vector _offset; + std::vector _global; + std::vector _local; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEREDUCEBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueUnmapBuffer.h b/dclasio/include/dclasio/message/EnqueueUnmapBuffer.h new file mode 100644 index 0000000..7aaf0cd --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueUnmapBuffer.h @@ -0,0 +1,118 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueUnmapBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel */ + +#ifndef ENQUEUEUNMAPBUFFER_H_ +#define ENQUEUEUNMAPBUFFER_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueUnmapBuffer: public Request { +public: + EnqueueUnmapBuffer(); + EnqueueUnmapBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + cl_map_flags map_flags, + size_t offset, + size_t cb, + const std::vector * eventIdWaitList = nullptr, + bool event = false); + EnqueueUnmapBuffer(const EnqueueUnmapBuffer& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + dcl::object_id bufferId() const; + cl_map_flags mapFlags() const; + size_t offset() const; + size_t cb() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_UNMAP_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _bufferId << _mapFlags + << _offset << _cb << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _bufferId >> _mapFlags + >> _offset >> _cb >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + dcl::object_id _bufferId; + cl_map_flags _mapFlags; + size_t _offset; + size_t _cb; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEUNMAPBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueWaitForEvents.h b/dclasio/include/dclasio/message/EnqueueWaitForEvents.h new file mode 100644 index 0000000..deb882e --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueWaitForEvents.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueWaitForEvents.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEWAITFOREVENTS_H_ +#define ENQUEUEWAITFOREVENTS_H_ + +#include "Request.h" + +#include +#include + +#include + +namespace dclasio { + +namespace message { + +class EnqueueWaitForEvents: public Request { +public: + EnqueueWaitForEvents(); + EnqueueWaitForEvents( + dcl::object_id commandQueueId, + const std::vector& eventIdList); + EnqueueWaitForEvents( + const EnqueueWaitForEvents& rhs); + + dcl::object_id commandQueueId() const; + const std::vector& eventIdList() const; + + static const class_type TYPE = 100 + ENQUEUE_WAIT_FOR_EVENTS; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _eventIdList; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _eventIdList; + } + +private: + dcl::object_id _commandQueueId; + std::vector _eventIdList; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEWAITFOREVENTS_H_ */ diff --git a/dclasio/include/dclasio/message/EnqueueWriteBuffer.h b/dclasio/include/dclasio/message/EnqueueWriteBuffer.h new file mode 100644 index 0000000..87eb8e9 --- /dev/null +++ b/dclasio/include/dclasio/message/EnqueueWriteBuffer.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueWriteBuffer.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef ENQUEUEWRITEBUFFER_H_ +#define ENQUEUEWRITEBUFFER_H_ + +#include "Request.h" + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +class EnqueueWriteBuffer : public Request { +public: + EnqueueWriteBuffer(); + EnqueueWriteBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + bool blocking_write, + size_t offset, + size_t cb, + const std::vector * eventWaitList = nullptr, + bool event = false); + EnqueueWriteBuffer( + const EnqueueWriteBuffer& rhs); + + dcl::object_id commandQueueId() const; + dcl::object_id commandId() const; + dcl::object_id bufferId() const; + bool blocking() const; + size_t offset() const; + size_t cb() const; + const std::vector& eventIdWaitList() const; + bool event() const; + + static const class_type TYPE = 100 + ENQUEUE_WRITE_BUFFER; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId << _commandId << _bufferId << _blocking << _offset << _cb << _eventIdWaitList << _event; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId >> _commandId >> _bufferId >> _blocking >> _offset >> _cb >> _eventIdWaitList >> _event; + } + +private: + dcl::object_id _commandQueueId; + dcl::object_id _commandId; + dcl::object_id _bufferId; + bool _blocking; + size_t _offset; + size_t _cb; + std::vector _eventIdWaitList; + bool _event; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ENQUEUEWRITEBUFFER_H_ */ diff --git a/dclasio/include/dclasio/message/ErrorResponse.h b/dclasio/include/dclasio/message/ErrorResponse.h new file mode 100644 index 0000000..72ab0b2 --- /dev/null +++ b/dclasio/include/dclasio/message/ErrorResponse.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ErrorResponse.h + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#ifndef ERRORRESPONSE_H_ +#define ERRORRESPONSE_H_ + +#include "Response.h" + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { +namespace message { + +class Request; + +/* ****************************************************************************/ + +class ErrorResponse: public Response { +public: + ErrorResponse(); + ErrorResponse(const Request& request, cl_int errcode); + ErrorResponse(const ErrorResponse& rhs); + virtual ~ErrorResponse(); + + cl_int get_errcode() const; + + /* TODO Replace message ID */ + static const class_type TYPE = 299; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Response::pack(buf); + buf << _errcode; + } + + void unpack(dcl::ByteBuffer& buf) { + Response::unpack(buf); + buf >> _errcode; + } + +private: + cl_int _errcode; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* ERRORRESPONSE_H_ */ diff --git a/dclasio/include/dclasio/message/EventProfilingInfosResponse.h b/dclasio/include/dclasio/message/EventProfilingInfosResponse.h new file mode 100644 index 0000000..2e54e27 --- /dev/null +++ b/dclasio/include/dclasio/message/EventProfilingInfosResponse.h @@ -0,0 +1,104 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EventProfilingInfosResponse.h + * + * \date 2013-10-27 + * \author Philipp Kegel + */ + +#ifndef EVENTPROFILINGINFOSRESPONSE_H_ +#define EVENTPROFILINGINFOSRESPONSE_H_ + +#include "Request.h" +#include "Response.h" + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { +namespace message { + +/*! + * \brief A response message containing all event profiling information. + */ +class EventProfilingInfosReponse: public DefaultResponse { +public: + EventProfilingInfosReponse(); + EventProfilingInfosReponse( + const Request& request, + cl_ulong received, + cl_ulong queued, + cl_ulong submit, + cl_ulong start, + cl_ulong end); + EventProfilingInfosReponse( + const EventProfilingInfosReponse& rhs); + virtual ~EventProfilingInfosReponse(); + + static const class_type TYPE = 200 + Request::GET_EVENT_PROFILING_INFOS; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + DefaultResponse::pack(buf); + buf << received << queued << submit << start << end; + } + + void unpack(dcl::ByteBuffer& buf) { + DefaultResponse::unpack(buf); + buf >> received >> queued >> submit >> start >> end; + } + + cl_ulong received; + cl_ulong queued; + cl_ulong submit; + cl_ulong start; + cl_ulong end; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* EVENTPROFILINGINFOSRESPONSE_H_ */ diff --git a/dclasio/include/dclasio/message/EventSynchronizationMessage.h b/dclasio/include/dclasio/message/EventSynchronizationMessage.h new file mode 100644 index 0000000..8ffa3db --- /dev/null +++ b/dclasio/include/dclasio/message/EventSynchronizationMessage.h @@ -0,0 +1,95 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EventSynchronizationMessage.h + * + * \date 2014-04-03 + * \author Philipp Kegel + */ + +#ifndef EVENTSYNCHRONIZATIONMESSAGE_H_ +#define EVENTSYNCHRONIZATIONMESSAGE_H_ + +#include "Message.h" + +#include +#include + +namespace dclasio { + +namespace message { + +/** + * @brief Request an update of memory objects, linked with this event. + * + * This message is sent by compute nodes to synchronize with an event, i.e. to + * update to the changes associated with the specified event. + */ +class EventSynchronizationMessage: public Message { +public: + EventSynchronizationMessage(); + EventSynchronizationMessage( + const dcl::object_id commandId); + EventSynchronizationMessage( + const EventSynchronizationMessage& rhs); + virtual ~EventSynchronizationMessage(); + + dcl::object_id commandId() const; + + static const class_type TYPE = 8802; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + buf << _commandId; + } + + void unpack(dcl::ByteBuffer& buf) { + buf >> _commandId; + } + +private: + dcl::object_id _commandId; +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* EVENTSYNCHRONIZATIONMESSAGE_H_ */ diff --git a/dclasio/include/dclasio/message/FinishRequest.h b/dclasio/include/dclasio/message/FinishRequest.h new file mode 100644 index 0000000..da381bf --- /dev/null +++ b/dclasio/include/dclasio/message/FinishRequest.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file FinishRequest.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef FINISHREQUEST_H_ +#define FINISHREQUEST_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { + +namespace message { + +class FinishRequest: public Request { +public: + FinishRequest(); + FinishRequest(dcl::object_id commandQueueId); + FinishRequest(const FinishRequest& rhs); + virtual ~FinishRequest(); + + dcl::object_id commandQueueId() const; + + static const class_type TYPE = 100 + FINISH; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId; + } + +private: + dcl::object_id _commandQueueId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* FINISHREQUEST_H_ */ diff --git a/dclasio/include/dclasio/message/FlushRequest.h b/dclasio/include/dclasio/message/FlushRequest.h new file mode 100644 index 0000000..5b7694e --- /dev/null +++ b/dclasio/include/dclasio/message/FlushRequest.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file FlushRequest.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef FLUSHREQUEST_H_ +#define FLUSHREQUEST_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +class FlushRequest: public Request { +public: + FlushRequest(); + FlushRequest(dcl::object_id commandQueueId); + FlushRequest(const FlushRequest& rhs); + virtual ~FlushRequest(); + + dcl::object_id commandQueueId() const; + + static const class_type TYPE = 100 + FLUSH; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _commandQueueId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _commandQueueId; + } + +private: + dcl::object_id _commandQueueId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* FLUSHREQUEST_H_ */ diff --git a/dclasio/include/dclasio/message/GetEventProfilingInfos.h b/dclasio/include/dclasio/message/GetEventProfilingInfos.h new file mode 100644 index 0000000..c921f51 --- /dev/null +++ b/dclasio/include/dclasio/message/GetEventProfilingInfos.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetEventProfilingInfos.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef GETEVENTPROFILINGINFOS_H_ +#define GETEVENTPROFILINGINFOS_H_ + +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +/*! + * \brief A request message for obtaining event profiling info. + */ +class GetEventProfilingInfos: public Request { +public: + GetEventProfilingInfos(); + GetEventProfilingInfos( + dcl::object_id eventID); + GetEventProfilingInfos( + const GetEventProfilingInfos& rhs); + virtual ~GetEventProfilingInfos(); + + dcl::object_id eventId() const; + + static const class_type TYPE = 100 + GET_EVENT_PROFILING_INFOS; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _eventId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _eventId; + } + +private: + dcl::object_id _eventId; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* GETEVENTPROFILINGINFOS_H_ */ diff --git a/dclasio/include/dclasio/message/GetKernelInfo.h b/dclasio/include/dclasio/message/GetKernelInfo.h new file mode 100644 index 0000000..2eade8d --- /dev/null +++ b/dclasio/include/dclasio/message/GetKernelInfo.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetKernelInfo.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef GETKERNELINFO_H_ +#define GETKERNELINFO_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { +namespace message { + +class GetKernelInfo: public Request { +public: + GetKernelInfo(); + GetKernelInfo(dcl::object_id kernelId, cl_kernel_info paramName); + GetKernelInfo(const GetKernelInfo& rhs); + virtual ~GetKernelInfo(); + + dcl::object_id kernelId() const; + cl_kernel_info paramName() const; + + static const class_type TYPE = 100 + GET_KERNEL_INFO; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _kernelId << _paramName; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _kernelId >> _paramName; + } + +private: + dcl::object_id _kernelId; + cl_kernel_info _paramName; +}; + +/* ****************************************************************************/ + +class GetKernelWorkGroupInfo: public Request { +public: + GetKernelWorkGroupInfo(); + GetKernelWorkGroupInfo( + dcl::object_id kernelId, + dcl::object_id deviceId, + cl_kernel_work_group_info paramName); + GetKernelWorkGroupInfo(const GetKernelWorkGroupInfo& rhs); + virtual ~GetKernelWorkGroupInfo(); + + dcl::object_id kernelId() const; + dcl::object_id deviceId() const; + cl_kernel_work_group_info paramName() const; + + static const class_type TYPE = 100 + GET_KERNEL_WORK_GROUP_INFO; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _kernelId << _deviceId << _paramName; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _kernelId >> _deviceId >> _paramName; + } +private: + dcl::object_id _kernelId; + dcl::object_id _deviceId; + cl_kernel_work_group_info _paramName; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* GETKERNELINFO_H_ */ diff --git a/dclasio/include/dclasio/message/GetProgramBuildLog.h b/dclasio/include/dclasio/message/GetProgramBuildLog.h new file mode 100644 index 0000000..3be2fb0 --- /dev/null +++ b/dclasio/include/dclasio/message/GetProgramBuildLog.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetProgramBuildLog.h + * + * \date 2014-04-06 + * \author Philipp Kegel + */ + +#ifndef GETPROGRAMBUILDLOG_H_ +#define GETPROGRAMBUILDLOG_H_ + +#include "Request.h" + +#include + +#include + +namespace dclasio { +namespace message { + +/*! + * \brief Query a program's build log. + * Other build info is provided locally. + */ +class GetProgramBuildLog: public Request { +public: + /*! + * \brief Creates a request for a program's build log + * + * \param[in] programId + * \param[in] deviceId + * \param[in] size maximum size of the build log to return + * An error will be returned by the compute node if the build log is longer this size. + * A value of 0 indicates that no build log should be returned. + */ + GetProgramBuildLog( + const dcl::object_id programId, + const dcl::object_id deviceId, + size_t size); + GetProgramBuildLog( + const GetProgramBuildLog& rhs); + virtual ~GetProgramBuildLog(); + + dcl::object_id programId() const; + dcl::object_id deviceId() const; + size_t size() const; + + static const value_type TYPE = 100 + GET_PROGRAM_BUILD_LOG; + + value_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _programId << _deviceId << _size; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _programId >> _deviceId >> _size; + } + +private: + dcl::object_id _programId; + dcl::object_id _deviceId; + size_t _size; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* GETPROGRAMBUILDLOG_H_ */ diff --git a/dclasio/include/dclasio/message/InfoResponse.h b/dclasio/include/dclasio/message/InfoResponse.h new file mode 100644 index 0000000..e76e32d --- /dev/null +++ b/dclasio/include/dclasio/message/InfoResponse.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file InfoResponse.h + * + * \date 2011-05-19 + * \author Philipp Kegel + */ + +#ifndef INFORESPONSE_H_ +#define INFORESPONSE_H_ + +#include "Response.h" + +#include +#include + +#include + +namespace dclasio { +namespace message { + +class Request; + +/* ****************************************************************************/ + +/*! + * \brief A response message containing a single piece of information on any type of OpenCL object. + */ +class InfoResponse: public DefaultResponse { +public: + InfoResponse(); + InfoResponse( + const Request& request, + size_t size, + const void * value); + InfoResponse( + const InfoResponse& rhs); + virtual ~InfoResponse(); + + dcl::Binary param() const; + + static const class_type TYPE = 298; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + DefaultResponse::pack(buf); + buf << _param; + } + + void unpack(dcl::ByteBuffer& buf) { + DefaultResponse::unpack(buf); + buf >> _param; + } + +private: + dcl::Binary _param; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* INFORESPONSE_H_ */ diff --git a/dclasio/include/dclasio/message/Message.h b/dclasio/include/dclasio/message/Message.h new file mode 100644 index 0000000..89a9a65 --- /dev/null +++ b/dclasio/include/dclasio/message/Message.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Message.h + * + * \date 2014-03-20 + * \author Philipp Kegel + */ + +#ifndef MESSAGE_H_ +#define MESSAGE_H_ + +#include + +#include +#include + +namespace dclasio { +namespace message { + +/*! + * \brief Message interface + */ +class Message { +public: + typedef uint32_t size_type; //! message size + typedef uint32_t class_type; //!< message type + + virtual ~Message() { } + + /*! + * \brief Returns the message type + * + * \return the message type + */ + virtual class_type get_type() const = 0; + + virtual void pack( + dcl::ByteBuffer& buf) const = 0; + virtual void unpack( + dcl::ByteBuffer& buf) = 0; +}; + +/* ****************************************************************************/ + +/*! + * \brief Abstract message base class providing the message type + */ +template +class BasicMessage : virtual public Message { +public: + static const class_type TYPE = Type; + + class_type get_type() const { + return TYPE; + } +}; + +/* ****************************************************************************/ + +/*! + * \brief Creates a default instance of a message of the specified type + * \param[in] type the type of message to create + * \return a message of type \c type + * \throw std::invalid_argument if the specified message type is unknown + */ +Message * createMessage( + Message::class_type type); + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* MESSAGE_H_ */ diff --git a/dclasio/include/dclasio/message/ReleaseRequest.h b/dclasio/include/dclasio/message/ReleaseRequest.h new file mode 100644 index 0000000..c9f83d1 --- /dev/null +++ b/dclasio/include/dclasio/message/ReleaseRequest.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ReleaseRequest.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef RELEASEREQUEST_H_ +#define RELEASEREQUEST_H_ + +#if 0 +#include "Request.h" + +#include +#include + +namespace dclasio { +namespace message { + +/*! + * \brief A generalization of the Delete... request messages + * + * !!! This template class is currently not used !!! + */ +template +class ReleaseRequest: public Request { +public: + ReleaseRequest( + dcl::object_id objectId); + ReleaseRequest( + const ReleaseRequest& rhs); + virtual ~ReleaseRequest(); + + dcl::object_id objectId() const { + return _objectId; + } + + static const value_type TYPE = TypeId; + + value_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _objectId; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _objectId; + } + +private: + dcl::object_id _objectId; +}; + +typedef ReleaseRequest<100 + Request::RELEASE_COMMAND_QUEUE> ReleaseCommandQueueRequest; +typedef ReleaseRequest<100 + Request::RELEASE_CONTEXT> ReleaseContextRequest; +typedef ReleaseRequest<100 + Request::RELEASE_EVENT> ReleaseEventRequest; +typedef ReleaseRequest<100 + Request::RELEASE_KERNEL> ReleaseKernelRequest; +typedef ReleaseRequest<100 + Request::RELEASE_MEM_OBJECT> ReleaseMemObjectRequest; +typedef ReleaseRequest<100 + Request::RELEASE_PROGRAM> ReleaseProgramRequest; + +} /* namespace message */ +} /* namespace dclasio */ +#endif + +#endif /* RELEASEREQUEST_H_ */ diff --git a/dclasio/include/dclasio/message/Request.h b/dclasio/include/dclasio/message/Request.h new file mode 100644 index 0000000..111384d --- /dev/null +++ b/dclasio/include/dclasio/message/Request.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Request.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef REQUEST_H_ +#define REQUEST_H_ + +#include + +#include +#include + +namespace dclasio { +namespace message { + +class Request: public Message { +public: + typedef uint32_t id_type; + + enum command : class_type { + INVALID = 0, + + GET_DEVICE_IDS = 1, + GET_DEVICE_INFO = 2, + + CREATE_CONTEXT = 11, + RELEASE_CONTEXT = 12, + + CREATE_BUFFER = 21, + RELEASE_MEM_OBJECT = 22, + + CREATE_COMMAND_QUEUE = 31, + RELEASE_COMMAND_QUEUE = 32, + + CREATE_PROGRAM_WITH_SOURCE = 41, + CREATE_PROGRAM_WITH_BINARY = 42, + RELEASE_PROGRAM = 43, + BUILD_PROGRAM = 44, + GET_PROGRAM_INFO = 45, + GET_PROGRAM_BUILD_LOG = 46, + + CREATE_KERNEL = 51, + CREATE_KERNELS_IN_PROGRAM = 52, + RELEASE_KERNEL = 53, + SET_KERNEL_ARG = 54, + SET_KERNEL_ARG_BINARY = 55, + SET_KERNEL_ARG_MEM_OBJECT = 56, + GET_KERNEL_INFO = 57, + GET_KERNEL_WORK_GROUP_INFO = 58, + + CREATE_EVENT = 61, + RELEASE_EVENT = 62, + GET_EVENT_PROFILING_INFOS = 63, + + FLUSH = 71, + FINISH = 72, + + ENQUEUE_READ_BUFFER = 81, + ENQUEUE_WRITE_BUFFER = 82, + ENQUEUE_COPY_BUFFER = 83, + ENQUEUE_NDRANGE_KERNEL = 84, + ENQUEUE_MARKER = 85, + ENQUEUE_WAIT_FOR_EVENTS = 86, + ENQUEUE_BARRIER = 87, + ENQUEUE_MAP_BUFFER = 88, + ENQUEUE_UNMAP_BUFFER = 89, + + ENQUEUE_BROADCAST_BUFFER = 91, + ENQUEUE_REDUCE_BUFFER = 92 + }; + + Request(); + Request( + const Request& rhs); + virtual ~Request(); + + virtual class_type get_type() const = 0; + + void pack(dcl::ByteBuffer& buf) const { + buf << id; + } + + void unpack(dcl::ByteBuffer& buf) { + buf >> id; + } + + id_type id; + +private: + static id_type requestCount; +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* REQUEST_H_ */ diff --git a/dclasio/include/dclasio/message/Response.h b/dclasio/include/dclasio/message/Response.h new file mode 100644 index 0000000..eff374e --- /dev/null +++ b/dclasio/include/dclasio/message/Response.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Response.h + * + * \date 2011-04-08 + * \author Philipp Kegel + */ + +#ifndef RESPONSE_H_ +#define RESPONSE_H_ + +#include "Message.h" +#include "Request.h" + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +namespace message { + +/*! + * \brief Abstract response message + */ +class Response : public Message { +public: + Response(); + Response(const Request& request); + Response(const Response& rhs); + virtual ~Response(); + + Request::id_type get_request_id() const; + + virtual cl_int get_errcode() const = 0; + + void pack(dcl::ByteBuffer& buf) const { + buf << _requestId; + } + + void unpack(dcl::ByteBuffer& buf) { + buf >> _requestId; + } + +private: + Request::id_type _requestId; +}; + +/* ****************************************************************************/ + +/*! + * \brief The default response type for successfully executed requests + */ +class DefaultResponse : public Response { +public: + DefaultResponse(); + DefaultResponse( + const Request& request); + DefaultResponse( + const DefaultResponse& rhs); + virtual ~DefaultResponse(); + + cl_int get_errcode() const; + + static const class_type TYPE = 200; + + class_type get_type() const { + return TYPE; + } +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* RESPONSE_H_ */ diff --git a/dclasio/include/dclasio/message/SetKernelArg.h b/dclasio/include/dclasio/message/SetKernelArg.h new file mode 100644 index 0000000..6caf55b --- /dev/null +++ b/dclasio/include/dclasio/message/SetKernelArg.h @@ -0,0 +1,188 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file SetKernelArg.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef SETKERNELARG_H_ +#define SETKERNELARG_H_ + +#include "Request.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { + +namespace message { + +/*! + * \brief A basic request message for setting a kernel argument. + * + * A base class to set kernel arguments on the compute node. + * Use SetKernelArgMemObject or SetKernelArgBinary to send arguments. + */ +class SetKernelArg: public Request { +public: + SetKernelArg(); + SetKernelArg(dcl::object_id kernelId, cl_uint index); + SetKernelArg(const SetKernelArg& rhs); + virtual ~SetKernelArg(); + + dcl::object_id kernelId() const; + cl_uint argIndex() const; +// virtual size_t argSize() const = 0; +// virtual const void * argSize() const = 0; + + static const class_type TYPE = 100 + SET_KERNEL_ARG; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << _kernelId << _index; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> _kernelId >> _index; + } + +private: + dcl::object_id _kernelId; + cl_uint _index; +}; + +/* ****************************************************************************/ + +/*! + * \brief A request message for setting an arbitrary kernel argument. + * + * Use SetKernelArgMemObject, if the argument is a memory object. + */ +class SetKernelArgBinary: public SetKernelArg { +public: + SetKernelArgBinary(); + SetKernelArgBinary( + dcl::object_id kernelId, + cl_uint index, + size_t size, + const void * value); + SetKernelArgBinary(const SetKernelArgBinary& rhs); + virtual ~SetKernelArgBinary(); + + size_t argSize() const; + const void * argValue() const; + + static const class_type TYPE = 100 + SET_KERNEL_ARG_BINARY; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + SetKernelArg::pack(buf); + buf << _arg; + } + + void unpack(dcl::ByteBuffer& buf) { + SetKernelArg::unpack(buf); + buf >> _arg; + } + +private: + dcl::Binary _arg; +}; + +/* ****************************************************************************/ + +/*! + * \brief A request message for setting a memory object as kernel argument. + */ +class SetKernelArgMemObject: public SetKernelArg { +public: + SetKernelArgMemObject(); + SetKernelArgMemObject(dcl::object_id kernelId, cl_uint index, size_t size); + SetKernelArgMemObject( + dcl::object_id kernelId, + cl_uint index, + dcl::object_id memObjectId); + SetKernelArgMemObject(const SetKernelArgMemObject& rhs); + virtual ~SetKernelArgMemObject(); + + size_t argSize() const; + const void * argValue() const; + dcl::object_id memObjectId() const; + + static const class_type TYPE = 100 + SET_KERNEL_ARG_MEM_OBJECT; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + SetKernelArg::pack(buf); + buf << _size << _memObjectId; + } + + void unpack(dcl::ByteBuffer& buf) { + SetKernelArg::unpack(buf); + buf >> _size >> _memObjectId; + } + +private: + size_t _size; + dcl::object_id _memObjectId; //!< memory object ID, or 0 for nullptr +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* SETKERNELARG_H_ */ diff --git a/dclasio/include/dclasio/message/message.dox b/dclasio/include/dclasio/message/message.dox new file mode 100644 index 0000000..89b32a4 --- /dev/null +++ b/dclasio/include/dclasio/message/message.dox @@ -0,0 +1,13 @@ +/*! + * \namespace dclasio::message + * \brief Message classes for the dOpenCL communication layer + * + * The message classes represent the requests and corresponding responses + * required for RPC as well as notification messages exchanged between the + * client driver and the daemon. + * + * The message classes should be removed from the API as they are intended for + * internal use by the communication layer. Currently, message are used by the + * client driver directly in conjunction with Process::sendMessage, as the + * dOpenCL API classes are not fully implemented yet. + */ \ No newline at end of file diff --git a/dclasio/src/dcl/ByteBuffer.cpp b/dclasio/src/dcl/ByteBuffer.cpp new file mode 100644 index 0000000..e82b943 --- /dev/null +++ b/dclasio/src/dcl/ByteBuffer.cpp @@ -0,0 +1,179 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ByteBuffer.cpp + * + * \date 2014-03-20 + * \author Philipp Kegel + */ + +#include +#include + +#include +#if USE_CSTRING +#include +#endif +#include +#include +#include +#include + +namespace dcl { + +ByteBuffer::ByteBuffer() : + _pos(0), _len(0), _max_size(DEFAULT_MAX_SIZE), _size(DEFAULT_SIZE), _bytes(new value_type[_size]) { } +ByteBuffer::ByteBuffer(size_type initial_size) : + _pos(0), _len(0), _max_size(DEFAULT_MAX_SIZE), _size(initial_size), _bytes(new value_type[_size]) { } +ByteBuffer::ByteBuffer(size_type size, value_type bytes[]) : + _pos(0), _len(size), _max_size(DEFAULT_MAX_SIZE), _size(size), _bytes(bytes) { } +ByteBuffer::ByteBuffer(ByteBuffer&& other) : + _pos(other._pos), _len(other._len), _max_size(DEFAULT_MAX_SIZE), _size(other._size), _bytes(std::move(other._bytes)) { } +ByteBuffer::~ByteBuffer() { } + +void ByteBuffer::set_max_size(size_type max_size) { + // max_size must not be reduced below current buffer size + if (max_size < _size) throw std::out_of_range("Buffer limit must be greater than buffer size"); + _max_size = max_size; +} + +ByteBuffer& ByteBuffer::operator<<(const bool flag) { + ensure_free(1); + _bytes[_len] = (flag ? 1 : 0); + ++_len; + return *this; +} + +#if USE_CSTRING +ByteBuffer& ByteBuffer::operator<<(const char *str) { + size_t size = strlen(str) + 1; // size of C string including terminating null character + ensure_free(size); + std::copy(str, str + size, end()); + _len += size; + return *this; +} +#endif + +ByteBuffer& ByteBuffer::operator<<(const std::string& str) { + auto size = str.size(); + operator<<(size); // write number of characters + ensure_free(size); + std::copy(std::begin(str), std::end(str), end()); + _len += size; + return *this; +} + +ByteBuffer& ByteBuffer::operator<<(const Binary& data) { + auto size = data.size(); + operator<<(size); // write number of bytes + ensure_free(size); + auto begin = static_cast(data.value()); + std::copy(begin, begin + size, end()); + _len += size; + return *this; +} + +ByteBuffer& ByteBuffer::operator>>(bool& flag) { + ensure_bytes(1); + flag = (_bytes[_pos] != 0); + ++_pos; + return *this; +} + +#if USE_CSTRING +ByteBuffer& ByteBuffer::operator>>(char *str) { + size_t size = strlen(reinterpret_cast(_bytes.get() + _pos)) + 1; + ensure_bytes(size); // fails if C string is not terminated (within this buffer) + std::copy(cbegin(), cbegin() + size, str); + _pos += size; + return *this; +} +#endif + +ByteBuffer& ByteBuffer::operator>>(std::string& str) { + size_t size; + operator>>(size); // read number of characters + ensure_bytes(size); + str.assign(cbegin(), size); + _pos += size; + return *this; +} + +ByteBuffer& ByteBuffer::operator>>(Binary& data) { + size_t size; + operator>>(size); // read number of bytes + ensure_bytes(size); + data.assign(size, cbegin()); + _pos += size; + return *this; +} + +void ByteBuffer::resize(size_type size_) { + reserve(size_); // no operation, if internal buffer size is greater or equal + _pos = 0; + _len = size_; +} + +ByteBuffer::size_type ByteBuffer::size() const { + return _len - _pos; +} + +ByteBuffer::iterator ByteBuffer::begin() { + return _bytes.get() + _pos; +} + +ByteBuffer::const_iterator ByteBuffer::begin() const { + return _bytes.get() + _pos; +} + +ByteBuffer::const_iterator ByteBuffer::cbegin() const { + return _bytes.get() + _pos; +} + +ByteBuffer::iterator ByteBuffer::end() { + return _bytes.get() + _len; +} + +ByteBuffer::const_iterator ByteBuffer::end() const { + return _bytes.get() + _len; +} + +ByteBuffer::const_iterator ByteBuffer::cend() const { + return _bytes.get() + _len; +} + +} // namespace dcl diff --git a/dclasio/src/dcl/CLError.cpp b/dclasio/src/dcl/CLError.cpp new file mode 100644 index 0000000..e0ca5f1 --- /dev/null +++ b/dclasio/src/dcl/CLError.cpp @@ -0,0 +1,78 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLError.cpp + * + * \date 2012-02-27 + * \author Philipp Kegel + */ + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dcl { + +CLError::CLError(cl_int err, const char *what) throw () : + _err(err) +{ + if (what) { + /* a string must not be initialized with NULL */ + _what.assign(what); + } +} + +CLError::CLError(cl_int err, const std::string& what) throw () : + _err(err), _what(what) { } + +CLError::~CLError() throw() { } + +const char * CLError::what() const throw() { + return _what.c_str(); +} + +cl_int CLError::err() const throw() { + return _err; +} + +} /* namespace dcl */ diff --git a/dclasio/src/dcl/CLObjectRegistry.cpp b/dclasio/src/dcl/CLObjectRegistry.cpp new file mode 100644 index 0000000..8918c55 --- /dev/null +++ b/dclasio/src/dcl/CLObjectRegistry.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLObjectRegistry.cpp + * + * \date 2012-07-31 + * \author Philipp Kegel + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace dcl { + +namespace detail { + +template +void Registry::bind(object_id id, T& object) { + _objects.insert(std::make_pair(id, &object)); +} + +template +void Registry::unbind(object_id id) { + _objects.erase(id); +} + +template +T * Registry::lookup(object_id id) const { + auto i = _objects.find(id); + return (i == std::end(_objects)) ? nullptr : i->second; +} + +/* explicit instantiation */ +template class Registry; +template class Registry; +template class Registry; +template class Registry; +template class Registry; +/* ^^^ add support for additional object types in registry here ^^^ */ + +} /* namespace detail */ + +/* ****************************************************************************/ + +CLObjectRegistry::CLObjectRegistry() { +} + +CLObjectRegistry::~CLObjectRegistry() { +} + +} /* namespace dcl */ diff --git a/dclasio/src/dcl/DCLException.cpp b/dclasio/src/dcl/DCLException.cpp new file mode 100644 index 0000000..37893c1 --- /dev/null +++ b/dclasio/src/dcl/DCLException.cpp @@ -0,0 +1,105 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DCLException.cpp + * + * \date 2012-02-27 + * \author Philipp Kegel + */ + +#include + +#include + +namespace dcl { + +DCLException::DCLException(const char *what) throw() { + if (what) { + /* a string must not be initialized with NULL */ + _what.assign(what); + } +} + +DCLException::DCLException(const std::string& what) throw () : + _what(what) { } + +DCLException::~DCLException() throw() { } + +const char * DCLException::what() const throw() { + return _what.c_str(); +} + +/******************************************************************************/ + +template +BasicException::BasicException(const char *what) throw() : + DCLException(what) { } + +template +BasicException::BasicException(const std::string& what) throw () : + DCLException(what) { } + +/* explicit instantiation */ +template class BasicException; +template class BasicException; +template class BasicException; + +/******************************************************************************/ + +InvalidArgument::InvalidArgument(int err, const char *what) throw () : + DCLException(what), _err(err) { } + +InvalidArgument::InvalidArgument(int err, const std::string& what) throw () : + DCLException(what), _err(err) { } + +InvalidArgument::~InvalidArgument() throw() { } + +int InvalidArgument::err() const throw() { + return _err; +} + +/******************************************************************************/ + +ThreadInterrupted::ThreadInterrupted(const char *what) throw() : + DCLException(what) { } + +ThreadInterrupted::ThreadInterrupted(const std::string& what) throw() : + DCLException(what) { } + +ThreadInterrupted::~ThreadInterrupted() throw() { } + +} /* namespace dcl */ diff --git a/dclasio/src/dcl/Remote.cpp b/dclasio/src/dcl/Remote.cpp new file mode 100644 index 0000000..90654a8 --- /dev/null +++ b/dclasio/src/dcl/Remote.cpp @@ -0,0 +1,69 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Remote.cpp + * + * \date 2011-04-12 + * \author Philipp Kegel + */ + +#include + +#include + +namespace dcl { + +object_id Remote::objectCount = 0; + +object_id Remote::generateId() { + /* TODO Ensure atomic increment */ + return ++objectCount; +} + +Remote::Remote() : + _id(generateId()) { } + +Remote::Remote(object_id id) : + _id(id) { } + +Remote::~Remote() { } + +object_id Remote::remoteId() const { + return _id; +} + +} /* namespace dcl */ diff --git a/dclasio/src/dcl/util/Clock.cpp b/dclasio/src/dcl/util/Clock.cpp new file mode 100644 index 0000000..c889e10 --- /dev/null +++ b/dclasio/src/dcl/util/Clock.cpp @@ -0,0 +1,85 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Clock.cpp + * + * @date 2013-02-27 + * @author Philipp Kegel + */ + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dcl { + +namespace util { + +Clock clock; + +/******************************************************************************/ + +Clock::Clock() : _start(std::chrono::high_resolution_clock::now()) { + sync(); +} + +Clock::~Clock() { +} + +cl_ulong Clock::getTime() { + /* get local elapsed time in nanoseconds */ + cl_ulong local_time = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - _start).count(); + + /* return local time adjusted to global clock */ + return local_time + _clockSkew; +} + +void Clock::sync() { + /* TODO Synchronize system clock with a global clock (e.g., using NTP) */ + _clockSkew = 0; +} + +} /* namespace util */ + +} /* namespace dcl */ diff --git a/dclasio/src/dcl/util/Logger.cpp b/dclasio/src/dcl/util/Logger.cpp new file mode 100644 index 0000000..5dd9527 --- /dev/null +++ b/dclasio/src/dcl/util/Logger.cpp @@ -0,0 +1,178 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Logger.cpp + * + * \date 2011-08-08 + * \author Michel Steuwer + * \author Philipp Kegel + */ + +#include + +#include +#include +#include +#include +#include + +namespace { + +auto start = std::chrono::high_resolution_clock::now(); + +} // unnamed namespace + +/******************************************************************************/ + +namespace dcl { + +namespace util { + +LoggerImpl Logger; + +// LoggerImpl implementation + +LoggerImpl::LoggerImpl() : + std::ostream(&_buffer), _currentSeverity(Severity::Info), _defaultSeverity( + Severity::Info), _maxSeverity(Severity::Warning), _buffer(*this, + std::clog) { +} + +void LoggerImpl::setOutput(std::ostream& output) { + _buffer.setOutput(output); +} + +/* TODO Distinguish logging level and message severity + * Logging level may be set to 'NONE' to disable logging, but message severity + * must not be 'NONE' */ +void LoggerImpl::setLoggingLevel(Severity severity) { + _maxSeverity = severity; +} + +void LoggerImpl::setDefaultSeverity(Severity severity) { + _defaultSeverity = severity; + _currentSeverity = severity; +} + +void LoggerImpl::setCurrentSeverity(Severity severity) { + _currentSeverity = severity; +} + +std::string LoggerImpl::severityToString(Severity severity) { + switch (severity) { + case Severity::Error: return "ERROR "; + case Severity::Warning: return "WARNING"; + case Severity::Info: return "INFO "; + case Severity::Debug: return "DEBUG "; + case Severity::Verbose: return "VERBOSE"; + default: return " "; + } +} + +LoggerImpl& operator<<( + LoggerImpl& logger, + LoggerImpl& (*manipulator)(LoggerImpl&)) { + return manipulator(logger); +} + +// LoggerBuffer implementation + +LoggerImpl::LoggerBuffer::LoggerBuffer(LoggerImpl& logger, std::ostream& stream) : + std::stringbuf(), _logger(logger), _output(&stream) { +} + +void LoggerImpl::LoggerBuffer::setOutput(std::ostream& output) { + _output = &output; +} + +int LoggerImpl::LoggerBuffer::sync() { + std::lock_guard lock(_mutex); + + if (_logger._currentSeverity <= _logger._maxSeverity) { + auto time = std::chrono::high_resolution_clock::now() - start; + (*_output) << _logger.severityToString(_logger._currentSeverity) << " [" + << std::chrono::duration_cast(time).count() + << ':' << std::setw(6) << std::setfill('0') + << (std::chrono::duration_cast(time).count() % 1000000) + << "] " << str(); + } + // clear buffer content + str(""); + // flush output + _output->flush(); + // reset logging level + _logger.setCurrentSeverity(_logger._defaultSeverity); + return 0; +} + +/* FIXME Logger manipulators are not thread-safe + * While one thread sets _currentSeverity for a message to be logged + * subsequently, a concurrent thread may change _currentSeverity before the + * message will be logged. + * Possible fix: use thread-local storage to set _currentSeverity for each + * thread. */ + +// LoggerImpl manipulators +LoggerImpl& Error(LoggerImpl& logger) { + logger.setCurrentSeverity(Severity::Error); + return logger; +} + +LoggerImpl& Warning(LoggerImpl& logger) { + logger.setCurrentSeverity(Severity::Warning); + return logger; +} + +LoggerImpl& Info(LoggerImpl& logger) { + logger.setCurrentSeverity(Severity::Info); + return logger; +} + +LoggerImpl& Debug(LoggerImpl& logger) { + logger.setCurrentSeverity(Severity::Debug); + return logger; +} + +LoggerImpl& Verbose(LoggerImpl& logger) { + logger.setCurrentSeverity(Severity::Verbose); + return logger; +} + +} // namespace util + +} // namespacce dcl + diff --git a/dclasio/src/dclasio/CommunicationManager.cpp b/dclasio/src/dclasio/CommunicationManager.cpp new file mode 100644 index 0000000..ec13d93 --- /dev/null +++ b/dclasio/src/dclasio/CommunicationManager.cpp @@ -0,0 +1,132 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommunicationManager.cpp + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#include "ComputeNodeCommunicationManagerImpl.h" +#include "HostCommunicationManagerImpl.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace { + +dcl::util::Severity getSeverity() { + const char *loglevel = getenv("DCL_LOG_LEVEL"); + + if (loglevel) { + if (strcmp(loglevel, "ERROR") == 0) { + return dcl::util::Severity::Error; + } else if (strcmp(loglevel, "WARNING") == 0) { + return dcl::util::Severity::Warning; + } else if (strcmp(loglevel, "INFO") == 0) { + return dcl::util::Severity::Info; + } else if (strcmp(loglevel, "DEBUG") == 0) { + return dcl::util::Severity::Debug; + } else if (strcmp(loglevel, "VERBOSE") == 0) { + return dcl::util::Severity::Verbose; + } + } + + // use default log level +#ifndef NDEBUG + return dcl::util::Severity::Debug; +#else + return dcl::util::Severity::Info; +#endif +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dcl { + +HostCommunicationManager * HostCommunicationManager::create() { + // set up dOpenCL logger + static std::ofstream dclLogFile("dcl_host.log"); + dcl::util::Logger.setOutput(dclLogFile); + dcl::util::Logger.setLoggingLevel(getSeverity()); + dcl::util::Logger.setDefaultSeverity(dcl::util::Severity::Info); + + return new dclasio::HostCommunicationManagerImpl(); +} + +/* ****************************************************************************/ + +ComputeNodeCommunicationManager * ComputeNodeCommunicationManager::create( + const std::string& url) { + std::string host; + dclasio::port_type port = dclasio::CommunicationManagerImpl::DEFAULT_PORT; + dclasio::CommunicationManagerImpl::resolve_url(url, host, port); + if (host.empty()) { + throw dcl::InvalidArgument(DCL_INVALID_NODE, "Missing host name"); + } + + // generate name of dOpenCL log file + std::string logFileName; + { + std::stringstream ss; + + /* TODO Log to system default location of files + * Log to /var/log/dcld */ + ss << "dcl_" << host << ".log"; + ss >> logFileName; + } + // set up dOpenCL logger + static std::ofstream dclLogFile(logFileName.c_str()); + dcl::util::Logger.setOutput(dclLogFile); + dcl::util::Logger.setLoggingLevel(getSeverity()); + dcl::util::Logger.setDefaultSeverity(dcl::util::Severity::Info); + + return new dclasio::ComputeNodeCommunicationManagerImpl(host, port); +} + +} /* namespace dcl */ diff --git a/dclasio/src/dclasio/CommunicationManagerImpl.cpp b/dclasio/src/dclasio/CommunicationManagerImpl.cpp new file mode 100644 index 0000000..1d028f0 --- /dev/null +++ b/dclasio/src/dclasio/CommunicationManagerImpl.cpp @@ -0,0 +1,323 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommunicationManagerImpl.cpp + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#include "CommunicationManagerImpl.h" + +#include "ComputeNodeImpl.h" +#include "DCLAsioTypes.h" +#include "HostImpl.h" +#include "ProcessImpl.h" + +#include "comm/CLEventProcessor.h" +#include "comm/DataDispatcher.h" + +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +/* **************************************************************************** + * Communication manager base implementation + ******************************************************************************/ + +const std::chrono::seconds CommunicationManagerImpl::DEFAULT_CONNECTION_TIMEOUT = std::chrono::seconds(3); + +void CommunicationManagerImpl::resolve_url( + const std::string& url, + std::string& hostName, + port_type& port) { + size_t delim = url.find(":"); + + hostName = url.substr(0, delim); + boost::trim(hostName); // remove leading and trailing white spaces + if (delim != std::string::npos) { + std::istringstream stream(url.substr(delim)); + port_type defaultPort = port; + + stream.ignore(); // skip delimiter + if ((stream >> port).fail()) { + port = defaultPort; + } + } +} + +dcl::process_id CommunicationManagerImpl::create_process_id( + const std::string& hostName, + port_type port) { + // FIXME Create unique process ID without host and port + dcl::process_id pid = 0; + + for (std::string::size_type i = 0; i < hostName.size(); ++i) { + pid += (unsigned char) hostName[i]; + pid <<= 4; + } + pid += port; + + return pid; +} + +CommunicationManagerImpl::CommunicationManagerImpl() : + _pid(create_process_id("", DEFAULT_PORT)), + _messageDispatcher(_pid), _dataDispatcher(_pid) { +} + +CommunicationManagerImpl::CommunicationManagerImpl( + const std::string& host, port_type port) : + _pid(create_process_id(host, port)), _messageDispatcher(_pid), _dataDispatcher(_pid) { + bind(host, port); +} + +CommunicationManagerImpl::~CommunicationManagerImpl() { +} + +void CommunicationManagerImpl::bind( + const std::string& host, port_type port) { + if (host.empty()) { + throw dcl::InvalidArgument(DCL_INVALID_NODE, "Missing host name"); + } + + // resolve local endpoint + boost::asio::ip::tcp::resolver resolver(_io_service); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), host, std::to_string(port)); + boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + + endpoint_type message_endpoint = *iterator; + endpoint_type data_endpoint( + message_endpoint.address(), message_endpoint.port() + 100); + + // bind local endpoints to connection acceptors + _messageDispatcher.bind(message_endpoint); + _dataDispatcher.bind(data_endpoint); + + dcl::util::Logger << dcl::util::Info + << "Bound to " << host << ':' << port + << std::endl; +} + +void CommunicationManagerImpl::start() { + _messageDispatcher.add_connection_listener(*this); + _messageDispatcher.add_message_listener(*this); + _dataDispatcher.add_connection_listener(*this); + _messageDispatcher.start(); + _dataDispatcher.start(); +} + +void CommunicationManagerImpl::stop() { + _messageDispatcher.remove_message_listener(*this); + _messageDispatcher.remove_connection_listener(*this); + _messageDispatcher.stop(); + _dataDispatcher.remove_connection_listener(*this); + _dataDispatcher.stop(); // cancel all data stream operations +} + +void CommunicationManagerImpl::createComputeNodes( + const std::vector& urls, + std::vector& computeNodes) { + assert(_clEventProcessor && "Event processor not initialized"); + computeNodes.clear(); + + for (const auto& url : urls) { + std::string host; + port_type port = DEFAULT_PORT; + + resolve_url(url, host, port); + if (host.empty()) { + dcl::util::Logger << dcl::util::Warning + << "Invalid URL '" << url << '\'' << std::endl; + continue; + } + boost::asio::ip::tcp::resolver resolver(_io_service); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), host, std::to_string(port)); + boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + + /* TODO Prevent creation of duplicates + * Connect message queue to obtain remote process ID and look for this + * ID in list of connected processes *and* pending process connections. + * Return the existing process, rather than a new one in this case. */ + + auto computeNode = new ComputeNodeImpl( + _messageDispatcher, _dataDispatcher, *iterator); + + /* A process does not have a valid process ID before it is connected. + * Hence, the compute node cannot be added to the list of compute nodes yet. */ + computeNodes.push_back(computeNode); + } +} + +void CommunicationManagerImpl::destroyComputeNode( + ComputeNodeImpl *computeNode) { + if (computeNode) { + computeNode->disconnect(); + { + std::lock_guard lock(_connectionsMutex); + _computeNodes.erase(computeNode->get_id()); + } + } else { + throw dcl::InvalidArgument(DCL_INVALID_NODE); + } +} + +ProcessImpl * CommunicationManagerImpl::get_process( + dcl::process_id pid) const { + return get_compute_node(pid); +} + +ComputeNodeImpl * CommunicationManagerImpl::get_compute_node( + dcl::process_id pid) const { + std::lock_guard lock(_connectionsMutex); + auto i = _computeNodes.find(pid); // search compute node list + return (i != std::end(_computeNodes)) ? i->second.get() : nullptr; +} + +void CommunicationManagerImpl::get_compute_nodes( + const std::vector& pids, + std::vector& computeNodes) const { + computeNodes.clear(); + std::lock_guard lock(_connectionsMutex); + for (auto pid : pids) { + auto i = _computeNodes.find(pid); + if (i == std::end(_computeNodes)) { // compute node not found + throw dcl::ConnectionException("Invalid process ID"); + } + computeNodes.push_back(i->second.get()); + } +} + +/* + * Connection listener API + */ + +bool CommunicationManagerImpl::approve_message_queue( + ProcessImpl::Type process_type, + dcl::process_id pid) { + return false; // reject all incoming connections +} + +void CommunicationManagerImpl::message_queue_connected( + comm::message_queue& msgq, + ProcessImpl::Type process_type, + dcl::process_id pid) { + // ignore process + dcl::util::Logger << dcl::util::Warning + << "Ignoring incoming connection" << std::endl; +} + +void CommunicationManagerImpl::message_queue_disconnected( + comm::message_queue& msgq) { + // ignore process disconnect + dcl::util::Logger << dcl::util::Warning + << "Ignoring closed connection" << std::endl; +} + +bool CommunicationManagerImpl::approve_data_stream( + dcl::process_id pid) { + // check if the source process is already registered + return (get_process(pid) != nullptr); +} + +void CommunicationManagerImpl::data_stream_connected( + comm::DataStream& data_stream, + dcl::process_id pid) { + /* The connections list must be locked, such that a node is not + * destroyed while its associated data stream is changed */ + std::lock_guard lock(_connectionsMutex); + + // lookup process for ID + auto process = get_process(pid); + if (process) { + /* TODO Log node type ('host' or 'compute node') */ + dcl::util::Logger << dcl::util::Info + << "Incoming data stream connection from process '" << process->url() + << "' (pid=" << process->get_id() << ')' + << std::endl; + + process->setDataStream(&data_stream); + } else { + dcl::util::Logger << dcl::util::Warning + << "Incoming data stream connection from unknown process" + << " (pid=" << process->get_id() << ')' + << std::endl; + } +} + +/* + * Message listener API + */ + +void CommunicationManagerImpl::message_received( + comm::message_queue& msgq, + const message::Message& message) { + // TODO Determine sender's process ID + dcl::process_id pid = msgq.get_process_id(); + + assert(_clEventProcessor && "No event processor"); + if (_clEventProcessor->dispatch(message, pid)) + return; + + // unknown message + dcl::util::Logger << dcl::util::Error + << "Received unknown message" << std::endl; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/CommunicationManagerImpl.h b/dclasio/src/dclasio/CommunicationManagerImpl.h new file mode 100644 index 0000000..e32c03d --- /dev/null +++ b/dclasio/src/dclasio/CommunicationManagerImpl.h @@ -0,0 +1,219 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommunicationManagerImpl.h + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#ifndef COMMUNICATIONMANAGERIMPL_H_ +#define COMMUNICATIONMANAGERIMPL_H_ + +#include "DCLAsioTypes.h" + +#include "comm/ConnectionListener.h" +#include "comm/DataDispatcher.h" +#include "comm/MessageDispatcher.h" +#include "comm/MessageListener.h" + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +class ComputeNodeImpl; +class ProcessImpl; + +namespace comm { + +class CLEventProcessor; +class DataStream; +class message_queue; + +} /* namespace comm */ + +/* ****************************************************************************/ + +/*! + * \brief An abstract base class for managing communication. + * + * Override methods {host|resourceManager|computeNode}Connection{Established|Lost|Approved} + * to define behavior in derived class. + */ +class CommunicationManagerImpl: + public virtual dcl::CommunicationManager, + public comm::connection_listener, + public comm::message_listener { +public: + //! default connection timeout is 3 seconds + static const std::chrono::seconds DEFAULT_CONNECTION_TIMEOUT; + + static const port_type DEFAULT_PORT = 25025; + + /*! + * \brief Extracts host name and port from a string. + * + * \param[in] url the URL to resolve + * \param[out] hostName a host name + * \param[in,out] port default port. + * If the URL contains a port number, it is returned by this parameter. + */ + static void resolve_url( + const std::string& url, + std::string& hostName, + port_type& port); + + static dcl::process_id create_process_id( + const std::string& hostName, + port_type port); + + + CommunicationManagerImpl(); + CommunicationManagerImpl( + const std::string& host, + port_type port); + virtual ~CommunicationManagerImpl(); + + void bind( + const std::string& host, + port_type port); + + void start(); + void stop(); + + /*! + * \brief Creates compute nodes from the given URLs. + * + * WARNING: Compute nodes returned by this method may are not connected + * and not owned by this communication manager yet. + * The compute nodes have to be connected in order to pass ownership to the + * communication manager. + * + * \param[in] urls remote endpoints + * \param[out] computeNodes compute nodes + */ + void createComputeNodes( + const std::vector& urls, + std::vector& computeNodes); + + void destroyComputeNode( + ComputeNodeImpl *computeNode); + + /*! + * \brief Returns the dOpenCL process that is associated with the specified ID. + * + * Subclasses may override this method in order to introduce additional + * process types. + * + * \param[in] pid the process ID + * \return the dOpenCL process that is associated with the specified process ID, + * or \c nullptr if no dOpenCL process is associated with the ID. + */ + virtual ProcessImpl * get_process( + dcl::process_id pid) const; + + ComputeNodeImpl * get_compute_node( + dcl::process_id pid) const; + + void get_compute_nodes( + const std::vector& pids, + std::vector& computeNodes) const; + + /* + * Connection listener API + */ + bool approve_message_queue( + ProcessImpl::Type process_type, + dcl::process_id pid); + + void message_queue_connected( + comm::message_queue& msgq, + ProcessImpl::Type process_type, + dcl::process_id pid); + + void message_queue_disconnected( + comm::message_queue& msgq); + + bool approve_data_stream( + dcl::process_id pid); + + void data_stream_connected( + comm::DataStream& data_stream, + dcl::process_id pid); + + /* + * Message listener API + */ + void message_received( + comm::message_queue& msgq, + const message::Message& message); + +protected: + /* Connection managers must be non-copyable */ + CommunicationManagerImpl( + const CommunicationManagerImpl&) = delete; + CommunicationManagerImpl& operator=( + const CommunicationManagerImpl&) = delete; + + boost::asio::io_service _io_service; + dcl::process_id _pid; //!< local process ID + comm::MessageDispatcher _messageDispatcher; + comm::DataDispatcher _dataDispatcher; + + std::unique_ptr _clEventProcessor; //!< Processor for dOpenCL messages + + std::unordered_map> _computeNodes; + mutable std::recursive_mutex _connectionsMutex; +}; + +} /* namespace dclasio */ + +#endif /* COMMUNICATIONMANAGERIMPL_H_ */ diff --git a/dclasio/src/dclasio/ComputeNode.cpp b/dclasio/src/dclasio/ComputeNode.cpp new file mode 100644 index 0000000..72e929e --- /dev/null +++ b/dclasio/src/dclasio/ComputeNode.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ComputeNode.cpp + * + * \date 01.11.2011 + * \author Philipp Kegel + */ + +#include + +#include +#include +#include + +#include + +#include +#include + +namespace dcl { + +void sendMessage( + const std::vector& computeNodes, + dclasio::message::Message& message) { + for (auto computeNode : computeNodes) { + computeNode->sendMessage(message); + } +} + +void sendRequest( + const std::vector& computeNodes, + dclasio::message::Request& request) { + for (auto computeNode : computeNodes) { + computeNode->sendRequest(request); + } +} + +void executeCommand( + const std::vector& computeNodes, + dclasio::message::Request& request, + dclasio::message::Response::class_type responseType, + std::vector> *responses) { + /* Send request to all compute nodes, such that the command is executed + * simultaneously */ + sendRequest(computeNodes, request); + + // Await responses from all compute nodes + /* TODO Receive message from *all* compute nodes, i.e., do not stop receipt on first failure */ + if (responses) { + responses->clear(); + responses->reserve(computeNodes.size()); + + for (auto computeNode : computeNodes) { + // move response into responses + responses->push_back( + computeNode->awaitResponse(request, responseType)); + } + } else { + for (auto computeNode : computeNodes) { + // discard response + computeNode->awaitResponse(request, responseType); + } + } +} + +} /* namespace dcl */ diff --git a/dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.cpp b/dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.cpp new file mode 100644 index 0000000..6f510b8 --- /dev/null +++ b/dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.cpp @@ -0,0 +1,364 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ComputeNodeCommunicationManagerImpl.cpp + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#include "ComputeNodeCommunicationManagerImpl.h" + +#include "ComputeNodeImpl.h" +#include "DCLAsioTypes.h" +#include "HostImpl.h" +#include "ProcessImpl.h" +#include "SmartCLObjectRegistry.h" + +#include "comm/CLEventProcessor.h" +#include "comm/CLRequestProcessor.h" +#include "comm/MessageDispatcher.h" +#include "comm/MessageQueue.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +/* **************************************************************************** + * Compute node communication manager implementation + ******************************************************************************/ + +ComputeNodeCommunicationManagerImpl::ComputeNodeCommunicationManagerImpl( + const std::string& host, port_type port) : + CommunicationManagerImpl(host, port), _daemon(nullptr) { + _clEventProcessor.reset(new comm::CLHostEventProcessor(*this)); + _clRequestProcessor.reset(new comm::CLRequestProcessor(*this)); +} + +ComputeNodeCommunicationManagerImpl::~ComputeNodeCommunicationManagerImpl() { +} + +SmartCLObjectRegistry& ComputeNodeCommunicationManagerImpl::objectRegistry() { + return _objectRegistry; +} + +void ComputeNodeCommunicationManagerImpl::connectComputeNodes( + const std::vector& computeNodes) { + assert(!"Fix ComputeNodeCommunicationManagerImpl::connectComputeNodes"); + + // Compute node that will connect to this process + std::set activeComputeNodes; + // Compute nodes that this process will connect to + std::set passiveComputeNodes; + + /* A collective node-to-node connection operation: + * A connection must be initiated by exactly one of the involved compute + * nodes. Therefore, compute nodes must agree on which ones actively connect + * while others passively accept connections. + * For this purpose, an order of compute nodes is derived from the order of + * message queue endpoints. Based on this order, computes nodes either have + * a 'lower' or 'higher' rank than others. + * A compute node only actively connects to other compute nodes that have a + * lower rank, and passively wait for connections from compute nodes with + * higher ranks. */ + + // Determine active and passive compute nodes + for (auto computeNode : computeNodes) { + assert(computeNode != nullptr); // compute node must not be NULL + + /* FIXME Do not compare compute nodes by process ID + * The process ID is 0 for non-connected processes. */ + if (computeNode->get_id() == _pid) { + /* a compute node cannot connect to itself */ + continue; + } + + if (computeNode->get_id() < _pid) { + // actively connect to passive compute nodes + passiveComputeNodes.insert(computeNode); + } else { + // await connection from active compute nodes + activeComputeNodes.insert(computeNode); + } + } + + // Connect to passive compute nodes (parallelized operation) + ComputeNodeImpl::connect( + std::vector(std::begin(passiveComputeNodes), std::end(passiveComputeNodes)), + ProcessImpl::Type::COMPUTE_NODE, _pid); + + // Await connection of active compute nodes + ComputeNodeImpl::awaitConnection( + std::vector(std::begin(activeComputeNodes), std::end(activeComputeNodes))); + + /* FIXME Add passive compute nodes (outgoing connections) to compute node list + * Active compute nodes (incoming connections) will be added by the message dispatcher */ +} + +void ComputeNodeCommunicationManagerImpl::setDaemon(dcl::Daemon *daemon) { + if (_daemon) { + /* TODO Deregister devices of old daemon */ + } + + _daemon = daemon; + + if (_daemon) { + std::vector devices; + + // Register devices + _daemon->getDevices(devices); + for (auto device : devices) { + _objectRegistry.bind(device->getId(), device); + } + } +} + +dcl::Daemon * ComputeNodeCommunicationManagerImpl::getDaemon() const { + return _daemon; +} + +bool ComputeNodeCommunicationManagerImpl::addConnectionListener( + dcl::ConnectionListener& listener) { + std::lock_guard lock(_connectionListenersMutex); + return (_connectionListeners.insert(&listener)).second; +} + +bool ComputeNodeCommunicationManagerImpl::removeConnectionListener( + dcl::ConnectionListener& listener) { + std::lock_guard lock(_connectionListenersMutex); + return (_connectionListeners.erase(&listener) == 1); +} + +ProcessImpl * ComputeNodeCommunicationManagerImpl::get_process( + dcl::process_id pid) const { + std::lock_guard lock(_connectionsMutex); + /* Do not use ComputeNodeCommunicationManagerImpl::getHost and + * CommunicationManagerImpl::getComputeNode to search for node in order to + * avoid multiple locking operations on _connectionsMutex */ + auto i = _hosts.find(pid); // search host list + if (i != std::end(_hosts)) return i->second.get(); + auto j = _computeNodes.find(pid); // search compute node list + if (j != std::end(_computeNodes)) return j->second.get(); + return nullptr; +} + +HostImpl * ComputeNodeCommunicationManagerImpl::get_host( + dcl::process_id pid) const { + std::lock_guard lock(_connectionsMutex); + auto i = _hosts.find(pid); // search host list + return (i != std::end(_hosts)) ? i->second.get() : nullptr; +} + +void ComputeNodeCommunicationManagerImpl::host_connected( + comm::message_queue& msgq, + dcl::process_id pid) { + auto host = std::unique_ptr(new HostImpl( + pid, _messageDispatcher, _dataDispatcher, msgq)); + bool accepted = false; + + // notify connection listeners + { + std::lock_guard lock(_connectionListenersMutex); + for (auto listener : _connectionListeners) { + /* WARNING: do not change expression order, otherwise short-cut + * evaluation might skip calling the listener */ + accepted = listener->connected(*host) || accepted; + } + } + + if (accepted) { + dcl::util::Logger << dcl::util::Debug + << "Accepted connection from host '" << host->url() << '\'' << std::endl; + // add host to list + { + std::lock_guard lock(_connectionsMutex); + bool inserted = _hosts.emplace(pid, std::move(host)).second; + assert(inserted && "Could not add host to list"); // assert insertion of host into list + } + } else { + dcl::util::Logger << dcl::util::Warning + << "Rejected connection from host '" << host->url() << '\'' << std::endl; + } +} + +void ComputeNodeCommunicationManagerImpl::compute_node_connected( + comm::message_queue& msgq, + dcl::process_id pid) { + auto computeNode = std::unique_ptr(new ComputeNodeImpl( + pid, _messageDispatcher, _dataDispatcher, msgq)); + bool accepted = false; + + // notify connection listeners + { + std::lock_guard lock(_connectionListenersMutex); + for (auto listener : _connectionListeners) { + /* WARNING: do not change expression order, otherwise short-cut + * evaluation might skip calling the listener */ + accepted = listener->connected(*computeNode) || accepted; + } + } + + if (accepted) { + dcl::util::Logger << dcl::util::Debug + << "Accepted connection from compute node '" << computeNode->url() << '\'' << std::endl; + // add compute node to list + { + std::lock_guard lock(_connectionsMutex); + bool inserted = _computeNodes.emplace(pid, std::move(computeNode)).second; + assert(inserted && "Could not add compute node to list"); // assert insertion of compute node into list + } + } else { + dcl::util::Logger << dcl::util::Warning + << "Rejected connection from compute node '" << computeNode->url() << '\'' << std::endl; + } +} + +/* + * Connection listener API + */ + +bool ComputeNodeCommunicationManagerImpl::approve_message_queue( + ProcessImpl::Type process_type, + dcl::process_id pid) { + /* TODO Allow multiple message queues per process and reconnecting of message queues + return true; // accept all incoming connections + */ + return (get_process(pid) == nullptr); // process ID must not be associated with a process yet +} + +void ComputeNodeCommunicationManagerImpl::message_queue_connected( + comm::message_queue& msgq, + ProcessImpl::Type process_type, + dcl::process_id pid) { + /* TODO Log node type ('host' or 'compute node') */ + dcl::util::Logger << dcl::util::Info + << "Incoming message queue connection" + << std::endl; + + // TODO Allow reconnecting of message queues + assert(get_process(pid) == nullptr); // process ID must not be associated with a process yet + + switch (process_type) { + case ProcessImpl::Type::HOST: + host_connected(msgq, pid); + break; + case ProcessImpl::Type::COMPUTE_NODE: + compute_node_connected(msgq, pid); + break; + default: + assert(!"Invalid process type"); + /* no break */ + } +} + +void ComputeNodeCommunicationManagerImpl::message_queue_disconnected( + comm::message_queue& msgq) { + // TODO Determine sender's process ID + dcl::process_id pid = msgq.get_process_id(); + + auto host = get_host(pid); + auto compute_node = get_compute_node(pid); + + if (host) { + assert(!compute_node); + + // notify connection listeners + std::lock_guard lock(_connectionListenersMutex); + for (auto listener : _connectionListeners) { + listener->disconnected(*host); + } + } else if (compute_node) { + assert(!host); + + // notify connection listeners + std::lock_guard lock(_connectionListenersMutex); + for (auto listener : _connectionListeners) { + listener->disconnected(*compute_node); + } + } else { + // unknown process disconnected + } + + // TODO Delete disconnected process + std::lock_guard lock(_connectionsMutex); + _hosts.erase(pid); + _computeNodes.erase(pid); +} + +/* + * Message listener API + */ + +void ComputeNodeCommunicationManagerImpl::message_received( + comm::message_queue& msgq, + const message::Message& message) { + // TODO Determine sender's process ID + dcl::process_id pid = msgq.get_process_id(); + + assert(_clEventProcessor && "No event processor"); + if (_clEventProcessor->dispatch(message, pid)) + return; + + assert(_clRequestProcessor && "No request processor"); + auto request = dynamic_cast(&message); + if (request && _clRequestProcessor->dispatch(*request, pid)) + return; + + // unknown message + dcl::util::Logger << dcl::util::Error + << "Received unknown message" << std::endl; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.h b/dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.h new file mode 100644 index 0000000..f9319c3 --- /dev/null +++ b/dclasio/src/dclasio/ComputeNodeCommunicationManagerImpl.h @@ -0,0 +1,162 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ComputeNodeCommunicationManagerImpl.h + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#ifndef COMPUTENODECOMMUNICATIONMANAGERIMPL_H_ +#define COMPUTENODECOMMUNICATIONMANAGERIMPL_H_ + +#include "CommunicationManagerImpl.h" +#include "DCLAsioTypes.h" +#include "ProcessImpl.h" +#include "SmartCLObjectRegistry.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +class ComputeNodeImpl; +class HostImpl; + +namespace comm { + +class CLRequestProcessor; +class message_queue; + +} /* namespace comm */ + +/* ****************************************************************************/ + +class ComputeNodeCommunicationManagerImpl: + public CommunicationManagerImpl, // extend CommunicationManagerImpl + public dcl::ComputeNodeCommunicationManager { // implement ComputeNodeCommunicationManager +public: + ComputeNodeCommunicationManagerImpl( + const std::string& host, port_type port); + virtual ~ComputeNodeCommunicationManagerImpl(); + + /*! + * \brief Returns this communication manager's application object registry. + * + * \return an application object registry + */ + SmartCLObjectRegistry& objectRegistry(); + + void connectComputeNodes( + const std::vector& computeNodes); + + void setDaemon( + dcl::Daemon *daemon = nullptr); + dcl::Daemon * getDaemon() const; + + bool addConnectionListener( + dcl::ConnectionListener& listener); + bool removeConnectionListener( + dcl::ConnectionListener& listener); + + /*! + * \brief Returns the dOpenCL process that is associated with a specified process ID. + * + * This method overrides CommunicationManagerImpl::getProcess in order to also + * search the list of hosts. + */ + ProcessImpl * get_process( + dcl::process_id pid) const; + + HostImpl * get_host( + dcl::process_id pid) const; + + /* + * Connection listener API + */ + bool approve_message_queue( + ProcessImpl::Type process_type, + dcl::process_id process_id); + + void message_queue_connected( + comm::message_queue& msgq, + ProcessImpl::Type process_type, + dcl::process_id process_id); + + void message_queue_disconnected( + comm::message_queue& msgq); + + /* + * Message listener API + */ + void message_received( + comm::message_queue& msgq, + const message::Message& message); + +private: + void host_connected( + comm::message_queue& msgq, + dcl::process_id process_id); + void compute_node_connected( + comm::message_queue& msgq, + dcl::process_id process_id); + + SmartCLObjectRegistry _objectRegistry; //!< Registry for application objects + + std::unique_ptr _clRequestProcessor; //!< Processor for command requests + + dcl::Daemon *_daemon; + std::set _connectionListeners; + std::mutex _connectionListenersMutex; + + std::unordered_map> _hosts; +}; + +} /* namespace dclasio */ + +#endif /* COMPUTENODECOMMUNICATIONMANAGERIMPL_H_ */ diff --git a/dclasio/src/dclasio/ComputeNodeImpl.cpp b/dclasio/src/dclasio/ComputeNodeImpl.cpp new file mode 100644 index 0000000..e1ee4be --- /dev/null +++ b/dclasio/src/dclasio/ComputeNodeImpl.cpp @@ -0,0 +1,399 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ComputeNodeImpl.cpp + * + * \date 2011-10-30 + * \author Philipp Kegel + */ + +#include "ComputeNodeImpl.h" + +#include "CommunicationManagerImpl.h" +#include "DCLAsioTypes.h" +#include "DeviceImpl.h" + +#include "comm/CLEventProcessor.h" +#include "comm/DataDispatcher.h" +#include "comm/MessageDispatcher.h" +#include "comm/MessageQueue.h" + +#include "message/DeviceIDsResponse.h" +#include "message/DeviceInfosResponse.h" +#include "message/GetDeviceIDs.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +void ComputeNodeImpl::updateDevices( + const std::vector& computeNodes) { + std::vector connectedComputeNodes(computeNodes); + + /* Send request to all compute nodes, such that the command is executed + * simultaneously */ + message::GetDeviceIDs request(static_cast(CL_DEVICE_TYPE_ALL)); + for (auto i = std::begin(connectedComputeNodes); i != std::end(connectedComputeNodes);) { + try { + (*i)->sendRequest(request); + ++i; + } catch (const dcl::DCLException& err) { + i = connectedComputeNodes.erase(i); + dcl::util::Logger << dcl::util::Warning + << err.what() << std::endl; + } + } + + // Await responses from all compute nodes + for (auto computeNode : connectedComputeNodes) { + try { + std::unique_ptr response( + static_cast( + computeNode->awaitResponse(request, message::DeviceIDsResponse::TYPE).release())); + assert(response != nullptr); // response must not be NULL + dcl::util::Logger << dcl::util::Info + << "Found " << response->deviceIds.size() + << " devices on compute node " << computeNode->url() << std::endl; + + computeNode->updateDevices(response->deviceIds); + } catch (const dcl::DCLException& err) { + dcl::util::Logger << dcl::util::Error << err.what() << std::endl; + } + } +} + +void ComputeNodeImpl::connect( + const std::vector& computeNodes, + Type localProcessType, + dcl::process_id pid) { + std::vector connectingComputeNodes(computeNodes); + + auto i = std::begin(connectingComputeNodes); + while (i != std::end(connectingComputeNodes)) { + // Skip connected compute nodes + if ((*i)->isConnected()) { + i = connectingComputeNodes.erase(i); + continue; + } + + try { + (*i)->connectMessageQueue(localProcessType, pid, + CommunicationManagerImpl::DEFAULT_CONNECTION_TIMEOUT); + ++i; + } catch (const dcl::DCLException& err) { + i = connectingComputeNodes.erase(i); + dcl::util::Logger << dcl::util::Warning << err.what() << std::endl; + } + } + + i = std::begin(connectingComputeNodes); + while (i != std::end(connectingComputeNodes)) { + try { + (*i)->connectDataStream(pid, + CommunicationManagerImpl::DEFAULT_CONNECTION_TIMEOUT); + ++i; + } catch (const dcl::DCLException& err) { + i = connectingComputeNodes.erase(i); + dcl::util::Logger << dcl::util::Error << err.what() << std::endl; + } + } +} + +void ComputeNodeImpl::awaitConnection( + const std::vector& computeNodes) { + auto deadline = std::chrono::system_clock::now() + + CommunicationManagerImpl::DEFAULT_CONNECTION_TIMEOUT; + for (auto computeNode : computeNodes) { + computeNode->awaitConnectionStatus(ProcessImpl::ConnectionStatus::CONNECTED, deadline); + } +} + +ComputeNodeImpl::ComputeNodeImpl( + dcl::process_id pid, + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + comm::message_queue& messageQueue) : + ProcessImpl(pid, messageDispatcher, dataDispatcher, messageQueue) +{ + dcl::util::Logger << dcl::util::Debug + << "Created compute node '" << url() << '\'' << std::endl; +} + +ComputeNodeImpl::ComputeNodeImpl( + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + const endpoint_type& endpoint) : + ProcessImpl(messageDispatcher, dataDispatcher, endpoint) +{ + dcl::util::Logger << dcl::util::Debug + << "Created compute node '" << url() << '\'' << std::endl; +} + +ComputeNodeImpl::~ComputeNodeImpl() { +} + +void ComputeNodeImpl::updateDevices() { + message::GetDeviceIDs request((cl_device_type) CL_DEVICE_TYPE_ALL); + std::unique_ptr response( + static_cast( + executeCommand(request, message::DeviceIDsResponse::TYPE).release())); + assert(response != nullptr); // response must not be NULL + dcl::util::Logger << dcl::util::Info + << "Found " << response->deviceIds.size() + << " devices on compute node " << url() << std::endl; + + updateDevices(response->deviceIds); +} + +void ComputeNodeImpl::updateDevices( + const std::vector& deviceIds) { + std::lock_guard lock(_devicesMutex); + + /* FIXME Do not clear but update the device list + * Add new devices; mark as valid + * Mark existing devices valid or invalid */ + if (_devices) { + _devices->clear(); + } else { + _devices.reset(new std::vector>()); + } + + _devices->reserve(deviceIds.size()); + for (auto deviceId : deviceIds) { + _devices->emplace_back(new DeviceImpl(deviceId, *this)); + // TODO Register devices + } +} + +void ComputeNodeImpl::connect(Type localProcessType, dcl::process_id pid) { + auto deadline = std::chrono::system_clock::now() + + CommunicationManagerImpl::DEFAULT_CONNECTION_TIMEOUT; + connectMessageQueue(localProcessType, pid, deadline); + connectDataStream(pid, deadline); +} + +void ComputeNodeImpl::getDevices(std::vector& devices) { + std::lock_guard lock(_devicesMutex); + + /* Device list may be uninitialized, if the compute node's device is queried + * for the first time. */ + if (!_devices) { + updateDevices(); + } + assert(_devices != nullptr); + + /* Must not return a reference to the device list as it may change + * asynchronously */ + for (const auto& device : *_devices) { + devices.push_back(device.get()); + } +} + +void ComputeNodeImpl::getInfo( + cl_compute_node_info_WWU param_name, + dcl::Binary& param) const { + // TODO Implement ComputeNodeImpl::getInfo + assert(!"ComputeNodeImpl::getInfo not implemented"); + + dcl::util::Logger << dcl::util::Info + << "Got compute node infos from '" << url() + << '\'' << std::endl; +} + +void ComputeNodeImpl::sendRequest(message::Request& request) const { + /* Do not use sendMessage which should be used for dOpenCL messages only + * Thus, sending messages and sending requests can be properly + * distinguished. */ + /* TODO Check message queue before sending message + if (!_messageQueue.isConnected()) { + throw dcl::IOException("No connection to compute node at " + url()); + } + */ + _messageQueue.send_message(request); +} + +std::unique_ptr ComputeNodeImpl::awaitResponse( + const message::Request& request, message::Response::class_type responseType) { + std::unique_ptr response; + + try { +#ifndef NDEBUG + // Wait for responses indefinitely during debug + response = _responseBuffer.get(request); +#else + /* FIXME Allow for blocking operation (e.g. finish) to wait indefinitely + * Blocking operations may require more time than the default response + * timeout. Hence no IO exception must be reported. + * ALTERNATIVELY implement blocking operations asynchronously. */ + response = _responseBuffer.get(request, DEFAULT_RESPONSE_TIMEOUT); +#endif + } catch (const dcl::ThreadInterrupted&) { + // ignore interrupt; treat as timeout + } + if (!response) { + throw dcl::IOException("No response from compute node at " + url()); + } + + // Intercept error message + if (response->get_type() == message::ErrorResponse::TYPE) { + throw dcl::CLError(response->get_errcode()); + } + // Intercept illegal response (protocol error) + if (response->get_type() != responseType) { + throw dcl::ProtocolException("Illegal response from compute node at " + url()); + } + + return response; +} + +void ComputeNodeImpl::awaitResponse(const message::Request& request) { + awaitResponse(request, message::DefaultResponse::TYPE); +} + +std::unique_ptr ComputeNodeImpl::executeCommand( + message::Request& request, message::Response::class_type responseType) { +//#ifndef NDEBUG +#if 0 + sendRequest(request); + dcl::util::Logger << dcl::util::Debug + << "\tsent request (request ID=" << request.id + << ", type=" << request.getType() << ')' + << std::endl; + + std::unique_ptr response = awaitResponse(request, responseType); + dcl::util::Logger << dcl::util::Debug + << "\treceived response (request ID=" << response->requestId + << ", type=" << response->getType() << ')' + << std::endl; + + return response; +#else + sendRequest(request); + return awaitResponse(request, responseType); +#endif +} + +void ComputeNodeImpl::executeCommand(message::Request& request) { + executeCommand(request, message::DefaultResponse::TYPE); +} + +comm::ResponseBuffer& ComputeNodeImpl::responseBuffer() { + return _responseBuffer; +} + +/* ****************************************************************************/ + +void sendMessage( + const std::vector& computeNodes, + message::Message& message) { + // TODO Use communication group to broadcast message + for (auto computeNode : computeNodes) { + computeNode->sendMessage(message); + } +} + +void sendRequest( + const std::vector& computeNodes, + message::Request& request) { + // TODO Use communication group to broadcast request + for (auto computeNode : computeNodes) { + computeNode->sendRequest(request); + } +} + +void executeCommand( + const std::vector& computeNodes, + message::Request& request, + message::Response::class_type responseType, + std::vector> *responses) { + /* Send request to all compute nodes, such that the command is executed + * simultaneously */ + sendRequest(computeNodes, request); + + // Await responses from all compute nodes + // TODO Receive message from *all* compute nodes, i.e., do not stop receipt on first failure + if (responses) { + responses->clear(); + responses->reserve(computeNodes.size()); + + for (auto computeNode : computeNodes) { + // move response into responses + responses->push_back( + computeNode->awaitResponse(request, responseType)); + } + } else { + for (auto computeNode : computeNodes) { + // discard response + computeNode->awaitResponse(request, responseType); + } + } +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/ComputeNodeImpl.h b/dclasio/src/dclasio/ComputeNodeImpl.h new file mode 100644 index 0000000..3fa012c --- /dev/null +++ b/dclasio/src/dclasio/ComputeNodeImpl.h @@ -0,0 +1,318 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ComputeNodeImpl.h + * + * \date 2011-10-30 + * \author Philipp Kegel + */ + +#ifndef COMPUTENODEIMPL_H_ +#define COMPUTENODEIMPL_H_ + +#include "ProcessImpl.h" + +#include "DCLAsioTypes.h" + +#include "comm/DataStream.h" +#include "comm/MessageDispatcher.h" +#include "comm/MessageQueue.h" +#include "comm/ResponseBuffer.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include + +namespace dclasio { + +class DeviceImpl; + +namespace comm { + +class DataDispatcher; +// FIXME MessageDispatcher header required by start_read_message hack +//class MessageDispatcher; + +} // namespace comm + +/* ****************************************************************************/ + +class ComputeNodeImpl: public dcl::ComputeNode, public ProcessImpl { +public: + /*! + * \brief Connects to multiple compute nodes concurrently. + * + * This method updates the compute nodes' device lists. + * This method works on a best-effort base: failed connection attempts are + * ignored. + * + * \param[in] computeNodes the compute nodes to connect to + * \param[in] localProcessType type of the local process that is establishing the connection + * \param[in] pid ID of the local process that is establishing the connection + */ + static void connect( + const std::vector& computeNodes, + Type localProcessType, + dcl::process_id pid); + + /*! + * \brief Awaits for multiple compute nodes to connect. + * + * \param[in] computeNodes the compute nodes which connection to wait for + */ + static void awaitConnection( + const std::vector& computeNodes); + + /*! + * \brief Updates the device lists of multiple compute nodes. + * + * The device IDs are queried from multiple remote compute nodes. + * This method is more efficient than \c updateDevices. + * + * \param[in] computeNode the compute node to query the device IDs from + */ + static void updateDevices( + const std::vector& computeNodes); + + + /*! + * \brief Creates a compute node instance from a message queue connection + * + * \param[in] id the compute node's process ID + * \param[in] messageDispatcher an associated message dispatcher + * \param[in] dataDispatcher an associated data dispatcher + * \param[in] messageQueue an associated message queue (owned by message dispatcher) + */ + ComputeNodeImpl( + dcl::process_id id, + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + comm::message_queue& messageQueue); + /*! + * \brief Creates a compute node instance for a remote endpoint. + * This compute node is not connected and has no valid process ID. + * + * \param[in] messageDispatcher an associated message dispatcher + * \param[in] dataDispatcher an associated data dispatcher + * \param[in] endpoint the remote endpoint associated with this process + */ + ComputeNodeImpl( + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + const endpoint_type& endpoint); + virtual ~ComputeNodeImpl(); + + /*! + * \brief Connects to the compute node + * + * A connection is established in four steps: + * 1. connect message queue + * 2. connect data stream + * 3. update device list + * + * \param[in] localProcessType type of the local process that is establishing the connection + * \param[in] pid ID of the local process that is establishing the connection + */ + /* TODO Allow for asynchronous connect using a callback */ + void connect( + Type localProcessType, + dcl::process_id pid); + + void getDevices( + std::vector& devices); + + void getInfo( + cl_compute_node_info_WWU param_name, + dcl::Binary& param) const; + + void sendRequest( + message::Request& request) const; + + std::unique_ptr awaitResponse( + const message::Request& request, + message::Response::class_type responseType); + void awaitResponse( + const message::Request& request); + + std::unique_ptr executeCommand( + message::Request& request, + message::Response::class_type responseType); + void executeCommand( + message::Request& request); + + comm::ResponseBuffer& responseBuffer(); + +private: + /*! + * \brief Connects to the compute node's message queue. + * + * \param[in] localProcessType type of the local process that is establishing the connection + * \param[in] pid ID of the local process that is establishing the connection + * \param[in] timeout timeout for connection process; may be a duration or time point + */ + template + void connectMessageQueue( + Type localProcessType, + dcl::process_id pid, + const timeout_type& timeout) { + std::lock_guard lock(_connectionStatusMutex); + // connect message queue to remote process + _pid = _messageQueue.connect(localProcessType, pid); + // TODO Connection asynchronously + if (_pid != 0) { + // FIXME Start reading messages automatically + _messageDispatcher.start_read_message(_messageQueue); + _connectionStatus = ConnectionStatus::MESSAGE_QUEUE_CONNECTED; + _connectionStatusChanged.notify_all(); + } else { + throw dcl::ConnectionException("Compute node '" + url() + "' refused connection"); + } + } + + /*! + * \brief Connects the compute node's data stream. + * + * \param[in] pid ID of the local process that is establishing the connection + * \param[in] timeout a timeout; may be a duration or time point + */ + template + void connectDataStream( + dcl::process_id pid, + const timeout_type& timeout) { + bool connected = awaitConnectionStatus(ConnectionStatus::MESSAGE_QUEUE_CONNECTED, timeout); + if (!connected) { /* session creation timed out */ + throw dcl::ConnectionException("Could not connect to compute node '" + url() + '\''); + } + + { + std::lock_guard lock(_connectionStatusMutex); + assert(_dataStream && "No data stream"); + if (_dataStream) { + if (_dataStream->connect(pid) != 0) { + _connectionStatus = ConnectionStatus::CONNECTED; + _connectionStatusChanged.notify_all(); + } else { + throw dcl::ConnectionException("Compute node '" + url() + "' refused connection"); + } + } + } + } + + /*! + * \brief Updates the compute nodes device list. + * The device IDs are queried from the remote compute node. + */ + void updateDevices(); + /*! + * \brief Updates the compute node's device list using a list of device IDs. + * + * \param[in] deviceIds the device IDs that should be used for the update + */ + void updateDevices( + const std::vector& deviceIds); + + + comm::ResponseBuffer _responseBuffer; //!< Response buffer + + std::unique_ptr>> _devices; //!< Device list + /*! + * \brief A mutex associated with this compute node's devices list. + * + * This mutex must be recursive as getDeviceIDs locks it and will attempt to + * lock it again when the device IDs have to be queried in updateDevices. + */ + std::recursive_mutex _devicesMutex; +}; + +/* ****************************************************************************/ + +/*! + * \brief Sends a message to multiple compute nodes. + * + * \param[in] computeNodes a list of compute nodes to send a message to + * \param[in] message the message to send + */ +void sendMessage( + const std::vector& computeNodes, + message::Message& message); + +/*! + * \brief Sends a request to multiple compute nodes. + * + * \param[in] computeNodes a list of compute nodes to send a request to + * \param[in] request the request to send + */ +void sendRequest( + const std::vector& computeNodes, + message::Request& request); + +/*! + * \brief Executes a command on multiple compute nodes. + * + * \param[in] computeNodes a list of compute node to execute the command on + * \param[in] request the request to send + * \param[in] responseType the expected type of responses + * \param[out] responses the responses returned by the compute nodes + */ +void executeCommand( + const std::vector& computeNodes, + message::Request& request, + message::Response::class_type responseType = message::DefaultResponse::TYPE, + std::vector> * responses = nullptr); + +} /* namespace dclasio */ + +#endif /* COMPUTENODEIMPL_H_ */ diff --git a/dclasio/src/dclasio/ContextListenerImpl.cpp b/dclasio/src/dclasio/ContextListenerImpl.cpp new file mode 100644 index 0000000..69e11f6 --- /dev/null +++ b/dclasio/src/dclasio/ContextListenerImpl.cpp @@ -0,0 +1,82 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ContextListenerImpl.cpp + * + * \date 2013-11-15 + * \author Philipp Kegel + */ + +#include "ContextListenerImpl.h" + +#include "HostImpl.h" + +#include "message/ContextErrorMessage.h" + +#include +#include +#include + +#include + +#include +#include + +namespace dclasio { + +ContextListenerImpl::ContextListenerImpl( + dcl::object_id id, HostImpl& host) : dcl::Remote(id), _host(host) { +} + +ContextListenerImpl::~ContextListenerImpl() { +} + +void ContextListenerImpl::onError( + const char *errorInfo, + const void *private_info, + size_t cb) { + message::ContextErrorMessage message(_id, errorInfo ? errorInfo : "", + dcl::Binary(cb, private_info)); + _host.sendMessage(message); + + dcl::util::Logger << dcl::util::Debug + << "Context error (ID=" << _id + << ", info=" << errorInfo + << ')' << std::endl; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/ContextListenerImpl.h b/dclasio/src/dclasio/ContextListenerImpl.h new file mode 100644 index 0000000..ce71cf1 --- /dev/null +++ b/dclasio/src/dclasio/ContextListenerImpl.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ContextListenerImpl.h + * + * \date 2013-11-15 + * \author Philipp Kegel + */ + +#ifndef CONTEXTLISTENERIMPL_H_ +#define CONTEXTLISTENERIMPL_H_ + +#include +#include +#include + +#include + +namespace dclasio { + +class HostImpl; + +/* ****************************************************************************/ + +class ContextListenerImpl : public dcl::ContextListener, public dcl::Remote { +public: + ContextListenerImpl( + dcl::object_id id, + HostImpl& host); + virtual ~ContextListenerImpl(); + + void onError( + const char *errorInfo, + const void *private_info, + size_t cb); + +private: + HostImpl& _host; +}; + +} /* namespace dclasio */ + +#endif /* CONTEXTLISTENERIMPL_H_ */ diff --git a/dclasio/src/dclasio/DCLAsioTypes.h b/dclasio/src/dclasio/DCLAsioTypes.h new file mode 100644 index 0000000..c61a5d3 --- /dev/null +++ b/dclasio/src/dclasio/DCLAsioTypes.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DCLAsioTypes.h + * + * \date 2014-03-30 + * \author Philipp Kegel + */ + +#ifndef DCLASIOTYPES_H_ +#define DCLASIOTYPES_H_ + +#include + +#include + +namespace dclasio { + +typedef uint16_t port_type; +typedef boost::asio::ip::tcp::endpoint endpoint_type; + +} /* namespace dclasio */ + +#endif /* DCLASIOTYPES_H_ */ diff --git a/dclasio/src/dclasio/DeviceImpl.cpp b/dclasio/src/dclasio/DeviceImpl.cpp new file mode 100644 index 0000000..45f2d09 --- /dev/null +++ b/dclasio/src/dclasio/DeviceImpl.cpp @@ -0,0 +1,94 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeviceImpl.cpp + * + * \date 2011-11-12 + * \author Philipp Kegel + */ + +#include "DeviceImpl.h" + +#include "ComputeNodeImpl.h" + +//#include "message/DeviceInfosResponse.h" +#include "message/GetDeviceInfo.h" + +#include + +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { + +DeviceImpl::DeviceImpl( + dcl::object_id id, + ComputeNodeImpl& computeNode) : + dcl::Remote(id), _computeNode(computeNode) { +} + +DeviceImpl::~DeviceImpl() { } + +void DeviceImpl::getInfo(cl_device_info param_name, dcl::Binary& param) const { + message::GetDeviceInfo request(_id, param_name); + std::unique_ptr response( + static_cast( + _computeNode.executeCommand(request, message::InfoResponse::TYPE).release())); + param = response->param(); + + dcl::util::Logger << dcl::util::Info + << "Got device info (ID=" << _id + << ')' << std::endl; +} + +ComputeNodeImpl& DeviceImpl::computeNode() const { + return _computeNode; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/DeviceImpl.h b/dclasio/src/dclasio/DeviceImpl.h new file mode 100644 index 0000000..2b62e1b --- /dev/null +++ b/dclasio/src/dclasio/DeviceImpl.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeviceImpl.h + * + * \date 2011-11-12 + * \author Philipp Kegel + */ + +#ifndef DEVICEIMPL_H_ +#define DEVICEIMPL_H_ + +#include "ComputeNodeImpl.h" + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +class DeviceImpl: public dcl::Device, public dcl::Remote { +public: + DeviceImpl( + dcl::object_id id, + ComputeNodeImpl& computeNode); + virtual ~DeviceImpl(); + + void getInfo( + cl_device_info param_name, + dcl::Binary& param) const; + + /* TODO Remove dclasio::DeviceImpl::getId */ + dcl::object_id getId() const { return _id; } + /* TODO Remove dclasio::DeviceImpl::getComputeNode */ + dcl::ComputeNode& getComputeNode() const { return _computeNode; } + + /*! + * \brief Returns the compute node associated with this device. + * + * \return a compute node + */ + ComputeNodeImpl& computeNode() const; + +private: + ComputeNodeImpl& _computeNode; +}; + +} /* namespace dclasio */ + +#endif /* DEVICEIMPL_H_ */ diff --git a/dclasio/src/dclasio/HostCommunicationManagerImpl.cpp b/dclasio/src/dclasio/HostCommunicationManagerImpl.cpp new file mode 100644 index 0000000..0f1cd7d --- /dev/null +++ b/dclasio/src/dclasio/HostCommunicationManagerImpl.cpp @@ -0,0 +1,166 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file HostCommunicationManagerImpl.cpp + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#include "HostCommunicationManagerImpl.h" + +#include "ComputeNodeImpl.h" +#include "HostImpl.h" + +#include "comm/CLEventProcessor.h" +#include "comm/CLResponseProcessor.h" + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +/* **************************************************************************** + * Host communication manager implementation + ******************************************************************************/ + +HostCommunicationManagerImpl::HostCommunicationManagerImpl() { + _clEventProcessor.reset(new comm::CLComputeNodeEventProcessor( + *this, _objectRegistry)); + _clResponseProcessor.reset(new comm::CLResponseProcessor(*this)); +} + +HostCommunicationManagerImpl::~HostCommunicationManagerImpl() { +} + +dcl::CLObjectRegistry& HostCommunicationManagerImpl::objectRegistry() { + return _objectRegistry; +} + +dcl::ComputeNode * HostCommunicationManagerImpl::createComputeNode( + const std::string& url) { + std::vector computeNodes; + + createComputeNodes({ url }, computeNodes); + assert(computeNodes.size() == 1); + if (computeNodes[0]) throw dcl::ConnectionException("Connection failed"); + + return computeNodes[0]; +} + +void HostCommunicationManagerImpl::createComputeNodes( + const std::vector& urls, + std::vector& computeNodes) { + std::vector createdComputeNodes; + CommunicationManagerImpl::createComputeNodes(urls, createdComputeNodes); + + /* TODO Implement connection process in communication manager + * The communication manager is able to detect a redundant connection + * based on the process ID that is returned during the connection process + * via the message queue. If a connection is already established, return + * the existing process, rather than creating a new one. + * WARNING This method must *not* delete compute nodes that have been + * returned as a replacement for a duplicate connection. */ + // TODO Connect asynchronously + // connect to compute nodes (parallelized operation) + ComputeNodeImpl::connect(createdComputeNodes, ProcessImpl::Type::HOST, _pid); + + // add connected compute nodes to compute node list + std::unique_lock lock(_connectionsMutex); + for (auto computeNode : createdComputeNodes) { + if (computeNode->isConnected()) { + assert(computeNode->get_id() != 0); + _computeNodes.emplace(computeNode->get_id(), std::unique_ptr(computeNode)); + computeNodes.push_back(computeNode); + } else { + delete computeNode; + computeNodes.push_back(nullptr); // return nullptr to indicate failed connection + } + } + lock.unlock(); + + // Prefetch device IDs + ComputeNodeImpl::updateDevices(createdComputeNodes); + /* TODO Handle connection error + * Devices of compute nodes whose connections failed should become unavailable. */ +} + +void HostCommunicationManagerImpl::destroyComputeNode( + dcl::ComputeNode *computeNode) { + destroyComputeNode(dynamic_cast(computeNode)); +} + +/* + * Message listener API + */ + +void HostCommunicationManagerImpl::message_received( + comm::message_queue& msgq, + const message::Message& message) { + // TODO Determine sender's process ID + dcl::process_id pid = msgq.get_process_id(); + + assert(_clEventProcessor && "No event processor"); + if (_clEventProcessor->dispatch(message, pid)) + return; + + assert(_clResponseProcessor && "No response processor"); + auto response = dynamic_cast(&message); + if (response && _clResponseProcessor->dispatch(*response, pid)) + return; + + dcl::util::Logger << dcl::util::Error + << "Received unknown message" << std::endl; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/HostCommunicationManagerImpl.h b/dclasio/src/dclasio/HostCommunicationManagerImpl.h new file mode 100644 index 0000000..d15653a --- /dev/null +++ b/dclasio/src/dclasio/HostCommunicationManagerImpl.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file HostCommunicationManagerImpl.h + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#ifndef HOSTCOMMUNICATIONMANAGERIMPL_H_ +#define HOSTCOMMUNICATIONMANAGERIMPL_H_ + +#include "CommunicationManagerImpl.h" + +#include +#include +#include + +#include +#include +#include + +namespace dclasio { + +class ComputeNodeImpl; + +namespace comm { + +class CLResponseProcessor; + +} // namespace message + +namespace message { + +class Message; + +} // namespace message + +/* ****************************************************************************/ + +class HostCommunicationManagerImpl: + public CommunicationManagerImpl, + public dcl::HostCommunicationManager { +public: + HostCommunicationManagerImpl(); + virtual ~HostCommunicationManagerImpl(); + + /*! + * \brief Returns this communication manager's application object registry. + * + * \return an application object registry + */ + dcl::CLObjectRegistry& objectRegistry(); + + /* + * Host communication manager API + */ + dcl::ComputeNode * createComputeNode( + const std::string& url); + void createComputeNodes( + const std::vector& urls, + std::vector& computeNodes); + void destroyComputeNode( + dcl::ComputeNode *computeNode); + + /* + * Message listener API + */ + void message_received( + comm::message_queue& msgq, + const message::Message& message); + +private: + dcl::CLObjectRegistry _objectRegistry; //!< Registry for application objects + + std::unique_ptr _clResponseProcessor; //!< Processor for command responses +}; + +} /* namespace dclasio */ + +#endif /* HOSTCOMMUNICATIONMANAGERIMPL_H_ */ diff --git a/dclasio/src/dclasio/HostImpl.cpp b/dclasio/src/dclasio/HostImpl.cpp new file mode 100644 index 0000000..d4715c4 --- /dev/null +++ b/dclasio/src/dclasio/HostImpl.cpp @@ -0,0 +1,79 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file HostImpl.cpp + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#include "HostImpl.h" + +#include "ProcessImpl.h" +#include "SmartCLObjectRegistry.h" + +#include "comm/DataDispatcher.h" +#include "comm/MessageDispatcher.h" +#include "comm/MessageQueue.h" + +#include + +#include + +#include + +namespace dclasio { + +HostImpl::HostImpl( + dcl::process_id id, + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + comm::message_queue& messageQueue) : + ProcessImpl(id, messageDispatcher, dataDispatcher, messageQueue) +{ + dcl::util::Logger << dcl::util::Debug + << "Created host " << url() << std::endl; +} + +HostImpl::~HostImpl() { +} + +SmartCLObjectRegistry& HostImpl::objectRegistry() { + return _objectRegistry; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/HostImpl.h b/dclasio/src/dclasio/HostImpl.h new file mode 100644 index 0000000..9b12483 --- /dev/null +++ b/dclasio/src/dclasio/HostImpl.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file HostImpl.h + * + * \date 2011-10-26 + * \author Philipp Kegel + */ + +#ifndef HOSTIMPL_H_ +#define HOSTIMPL_H_ + +#include "ProcessImpl.h" +#include "SmartCLObjectRegistry.h" + +#include +#include + +#include + +namespace dclasio { + +namespace comm { + +class DataDispatcher; +class MessageDispatcher; +class message_queue; + +} // namespace comm + +/* ****************************************************************************/ + +/*! + * \brief An implementation of the host interface of the dOpenCL C++ compute node API. + */ +class HostImpl: public dcl::Host, public ProcessImpl { +public: + /*! + * \brief Creates a host instance from a message queue connection + * The data stream will be attached to this process later on using setDataStream. + * + * \param[in] id the host's process ID + * \param[in] messageDispatcher an associated message dispatcher + * \param[in] dataDispatcher an associated data dispatcher + * \param[in] messageQueue an associated message queue (owned by message dispatcher) + */ + HostImpl( + dcl::process_id id, + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + comm::message_queue& messageQueue); + virtual ~HostImpl(); + + /* TODO Replace HostImpl::objectRegistry by ComputeNodeCommunicationManagerImpl::objectRegistry + * HostImpl::objectRegistry is a temporary solution to ensure unique IDs + * when multiple hosts are connected to a daemon. + * Eventually, CommunicationManagerImpl::objectRegistry should be the global + * registry used by all hosts and compute nodes. */ + SmartCLObjectRegistry& objectRegistry(); + +private: + SmartCLObjectRegistry _objectRegistry; +}; + +} /* namespace dclasio */ + +#endif /* HOSTIMPL_H_ */ diff --git a/dclasio/src/dclasio/ProcessImpl.cpp b/dclasio/src/dclasio/ProcessImpl.cpp new file mode 100644 index 0000000..02e26af --- /dev/null +++ b/dclasio/src/dclasio/ProcessImpl.cpp @@ -0,0 +1,201 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProcessImpl.cpp + * + * \date 2012-03-18 + * \author Philipp Kegel + */ + +#include "ProcessImpl.h" + +#include "DCLAsioTypes.h" + +#include "comm/DataDispatcher.h" +#include "comm/DataStream.h" +#include "comm/MessageDispatcher.h" +#include "comm/MessageQueue.h" + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +const std::chrono::seconds ProcessImpl::DEFAULT_RESPONSE_TIMEOUT = std::chrono::seconds(3); + +ProcessImpl::ProcessImpl( + dcl::process_id id, + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + comm::message_queue& msgq) : + _pid(id), + _messageDispatcher(messageDispatcher), _messageQueue(msgq), + _dataDispatcher(dataDispatcher), _dataStream(nullptr), + _connectionStatus(ConnectionStatus::MESSAGE_QUEUE_CONNECTED) { + assert(_pid != 0 && "Invalid process ID"); +} + +ProcessImpl::ProcessImpl( + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + const endpoint_type& endpoint) : + _pid(0) /* unknown process ID */, + _messageDispatcher(messageDispatcher), + _messageQueue(*_messageDispatcher.create_message_queue(endpoint)), + _dataDispatcher(dataDispatcher), + _connectionStatus(ConnectionStatus::DISCONNECTED) { + endpoint_type data_endpoint(endpoint.address(), endpoint.port() + 100); + _dataStream = _dataDispatcher.create_data_stream(data_endpoint); +} + +ProcessImpl::~ProcessImpl() { + disconnect(); + + _messageDispatcher.destroy_message_queue(&_messageQueue); +} + +dcl::process_id ProcessImpl::get_id() const { + return _pid; +} + +void ProcessImpl::disconnect() { + std::lock_guard lock(_connectionStatusMutex); + + // disconnect message queue + _messageQueue.disconnect(); + + // detach data stream from process + if (_dataStream) { + _dataDispatcher.destroy_data_stream(_dataStream); + _dataStream = nullptr; + } + + _connectionStatus = ConnectionStatus::DISCONNECTED; + _connectionStatusChanged.notify_all(); +} + +bool ProcessImpl::isConnected() { + std::lock_guard lock(_connectionStatusMutex); + return _connectionStatus == ConnectionStatus::CONNECTED; +} + +const std::string& ProcessImpl::url() const { + if (_url.empty()) { + std::stringstream ss; + + // TODO Generate process URL from message queue's remote endpoint + /* + // create URL string once + if (!(ss << _messageQueue.getHostname() << ':' << _messageQueue.getPort()) || + !(ss >> _url) || + !((ss >> std::ws).eof())) // skip whitespace and check if EOF flag has been set + _url.clear(); + */ + } + + return _url; +} + +void ProcessImpl::sendMessage(const message::Message& message) const { + /* TODO Check message queue before sending message + if (!_messageQueue.isConnected()) { + throw dcl::IOException("No connection to process at " + url()); + } + */ + _messageQueue.send_message(message); +} + +std::shared_ptr ProcessImpl::sendData(size_t size, + const void *ptr) { + return getDataStream().write(size, ptr); +} + +std::shared_ptr ProcessImpl::receiveData(size_t size, + void *ptr) { + return getDataStream().read(size, ptr); +} + +comm::DataStream& ProcessImpl::getDataStream() { + std::lock_guard lock(_connectionStatusMutex); + while (!_dataStream) { + /* TODO Use timed wait when waiting for data stream; + * throw dcl::ConnectionException after timeout. + * This method is deadlock-prone. However, without it (see sendData and + * receiveData) the data stream sometimes is not ready when sending or + * receiving data, in particular when using a large number (>=32) of + * compute nodes. */ + _dataStreamReady.wait(_connectionStatusMutex); + } + return *_dataStream; +} + +void ProcessImpl::setDataStream( + comm::DataStream *dataStream) { + { + std::lock_guard lock(_connectionStatusMutex); + std::swap(_dataStream, dataStream); + if (_dataStream) { + assert(_connectionStatus == ConnectionStatus::MESSAGE_QUEUE_CONNECTED); + _connectionStatus = ConnectionStatus::CONNECTED; + _dataStreamReady.notify_all(); + } + } + + // destroy old data stream + if (dataStream) { + _dataDispatcher.destroy_data_stream(dataStream); + } +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/ProcessImpl.h b/dclasio/src/dclasio/ProcessImpl.h new file mode 100644 index 0000000..db7a614 --- /dev/null +++ b/dclasio/src/dclasio/ProcessImpl.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProcessImpl.h + * + * \date 2012-03-18 + * \author Philipp Kegel + */ + +#ifndef PROCESSIMPL_H_ +#define PROCESSIMPL_H_ + +#include "DCLAsioTypes.h" + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +class DataDispatcher; +class DataStream; +class MessageDispatcher; +class message_queue; + +} // namespace comm + +/* ****************************************************************************/ + +/*! + * \brief An implementation the dOpenCL Process interface. + */ +class ProcessImpl: public virtual dcl::Process { +public: + enum class Type : char { + HOST, + COMPUTE_NODE + }; + + enum class ConnectionStatus : unsigned int { + DISCONNECTED = 0, + MESSAGE_QUEUE_CONNECTED = 1, + DATA_STREAM_CONNECTED = 1 << 1, + CONNECTED = MESSAGE_QUEUE_CONNECTED | DATA_STREAM_CONNECTED + }; + + //! default response timeout is 3 seconds + static const std::chrono::seconds DEFAULT_RESPONSE_TIMEOUT; + + + /*! + * \brief Creates a process instance from a message queue connection + * The data stream will be attached to this process later on using setDataStream. + * + * \param[in] id the process' ID + * The process ID has been obtained via the message queue + * \param[in] messageDispatcher an associated message dispatcher + * \param[in] dataDispatcher an associated data dispatcher + * \param[in] messageQueue an associated message queue (owned by message dispatcher). + * The message queue also provides the remote endpoint associated with this process + */ + ProcessImpl( + dcl::process_id id, + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + comm::message_queue& messageQueue); + /*! + * \brief Creates a process instance for a remote endpoint. + * This process is not connected and has no valid process ID. + * + * \param[in] messageDispatcher an associated message dispatcher + * \param[in] dataDispatcher an associated data dispatcher + * \param[in] endpoint the remote endpoint associated with this process + */ + ProcessImpl( + comm::MessageDispatcher& messageDispatcher, + comm::DataDispatcher& dataDispatcher, + const endpoint_type& endpoint); + virtual ~ProcessImpl(); + + /*! + * \brief Returns this process' ID + * @return the process ID + */ + dcl::process_id get_id() const; + + /*! + * \brief Disconnects the process + * + * A connection is disconnected in two steps: + * 1. destroy data stream + * 2. disconnect message queue + */ + void disconnect(); + /*! + * \brief Tests, if the compute node is connected + * + * \return \c true, if the compute node is connected, otherwise \c false + */ + bool isConnected(); + + const std::string& url() const; + + void sendMessage( + const message::Message& message) const; + + std::shared_ptr sendData( + size_t size, + const void *ptr); + std::shared_ptr receiveData( + size_t size, + void * ptr); + + /*! + * \brief (Un)sets the processes data stream + * + * This method is called internally by the communication manager. + * + * \param[in] dataStream a connected data stream or \c nullptr + */ + void setDataStream( + comm::DataStream *dataStream = nullptr); + +protected: + /*! + * \brief Waits until a given connection status has been reached, or a specified timeout expired + * + * \param[in] status the connection status to wait for + * \param[in] timeout the maximum duration to wait for the specified connection status + * \return \c false if timeout has been reached, otherwise \c true. + */ + template + bool awaitConnectionStatus( + ConnectionStatus status, + const std::chrono::duration& timeout) { + std::lock_guard lock(_connectionStatusMutex); + while (_connectionStatus != status) { + if (_connectionStatusChanged.wait_for(_connectionStatusMutex, timeout) == std::cv_status::timeout) { + // timeout expired + break; + } + } + return (_connectionStatus == status); + } + + /*! + * \brief Waits until a given connection status or time point has been reached + * + * \param[in] status the connection status to wait for + * \param[in] deadline the time to stop waiting + * \return \c false if deadline has been reached, otherwise \c true. + */ + template + bool awaitConnectionStatus( + ConnectionStatus status, + const std::chrono::time_point& deadline) { + std::lock_guard lock(_connectionStatusMutex); + while (_connectionStatus != status) { + if (_connectionStatusChanged.wait_until(_connectionStatusMutex, deadline) == std::cv_status::timeout) { + // deadline reached + break; + } + } + return (_connectionStatus == status); + } + + /*! + * \brief Returns the process' associated data stream + * This method blocks until the data stream is available + * + * \return a data stream + */ + comm::DataStream& getDataStream(); + + dcl::process_id _pid; //!< process ID + + comm::MessageDispatcher& _messageDispatcher; + comm::message_queue& _messageQueue; //!< message queue associated with this process; is owned by message dispatcher + comm::DataDispatcher& _dataDispatcher; + comm::DataStream *_dataStream; //!< data stream associated with this process; is owned by data dispatcher + std::condition_variable_any _dataStreamReady; + + ConnectionStatus _connectionStatus; //!< Process connection status + std::recursive_mutex _connectionStatusMutex; //!< Protects _connectionStatus and _dataStream + std::condition_variable_any _connectionStatusChanged; + +private: + /* Processes must be non-copyable */ + ProcessImpl( + const ProcessImpl&) = delete; + ProcessImpl& operator=( + const ProcessImpl&) = delete; + + mutable std::string _url; //!< Process URL +}; + +} /* namespace dclasio */ + +#endif /* PROCESSIMPL_H_ */ diff --git a/dclasio/src/dclasio/ProgramBuildListenerImpl.cpp b/dclasio/src/dclasio/ProgramBuildListenerImpl.cpp new file mode 100644 index 0000000..b580847 --- /dev/null +++ b/dclasio/src/dclasio/ProgramBuildListenerImpl.cpp @@ -0,0 +1,98 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProgramBuildListenerImpl.cpp + * + * \date 2013-11-14 + * \author Philipp Kegel + */ + +#include "ProgramBuildListenerImpl.h" + +#include "DeviceImpl.h" +#include "HostImpl.h" + +#include "message/ProgramBuildMessage.h" + +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dclasio { + +ProgramBuildListenerImpl::ProgramBuildListenerImpl( + dcl::object_id id, HostImpl& host) : Remote(id), _host(host) { +} + +ProgramBuildListenerImpl::~ProgramBuildListenerImpl() { +} + +void ProgramBuildListenerImpl::onComplete( + const std::vector& devices, + const std::vector& buildStatus) { + std::vector deviceIds; + + deviceIds.reserve(devices.size()); + for (auto device : devices) { + auto deviceImpl = dynamic_cast(device); + assert(deviceImpl != nullptr); + deviceIds.push_back(deviceImpl->remoteId()); + } + + message::ProgramBuildMessage message(_id, deviceIds, buildStatus); + _host.sendMessage(message); + /* TODO Handle errors */ + + dcl::util::Logger << dcl::util::Debug + << "Sent update of program build status (ID=" << _id + << ')' << std::endl; +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/ProgramBuildListenerImpl.h b/dclasio/src/dclasio/ProgramBuildListenerImpl.h new file mode 100644 index 0000000..5f530d5 --- /dev/null +++ b/dclasio/src/dclasio/ProgramBuildListenerImpl.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProgramBuildListenerImpl.h + * + * \date 2013-11-14 + * \author Philipp Kegel + */ + +#ifndef PROGRAMBUILDLISTENERIMPL_H_ +#define PROGRAMBUILDLISTENERIMPL_H_ + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { + +class HostImpl; + +/* ****************************************************************************/ + +class ProgramBuildListenerImpl: public dcl::ProgramBuildListener, public dcl::Remote { +public: + ProgramBuildListenerImpl( + dcl::object_id id, + HostImpl& host); + virtual ~ProgramBuildListenerImpl(); + + void onComplete( + const std::vector& devices, + const std::vector& buildStatus); + +private: + HostImpl& _host; +}; + +} /* namespace dclasio */ + +#endif /* PROGRAMBUILDLISTENERIMPL_H_ */ diff --git a/dclasio/src/dclasio/SmartCLObjectRegistry.cpp b/dclasio/src/dclasio/SmartCLObjectRegistry.cpp new file mode 100644 index 0000000..287ad67 --- /dev/null +++ b/dclasio/src/dclasio/SmartCLObjectRegistry.cpp @@ -0,0 +1,69 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file SmartCLObjectRegistry.cpp + * + * \date 2013-10-22 + * \author Philipp Kegel + */ + +#include "SmartCLObjectRegistry.h" + +#include +#include + +#include + +namespace dclasio { + +SmartCLObjectRegistry::SmartCLObjectRegistry() { +} + +SmartCLObjectRegistry::~SmartCLObjectRegistry() { +} + +void SmartCLObjectRegistry::unbindMemory(dcl::object_id id) { + detail::Registry>::unbind(id); +} + +std::shared_ptr SmartCLObjectRegistry::lookupMemory( + dcl::object_id id) const { + return std::dynamic_pointer_cast( + detail::Registry>::lookup(id)); +} + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/SmartCLObjectRegistry.h b/dclasio/src/dclasio/SmartCLObjectRegistry.h new file mode 100644 index 0000000..c42216f --- /dev/null +++ b/dclasio/src/dclasio/SmartCLObjectRegistry.h @@ -0,0 +1,206 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file SmartCLObjectRegistry.h + * + * An implementation of an object registry. + * This class is similar to CLObjectRegistry but provides special handling for smart pointers. + * It does not hold ownership of registered objects but uses either pointers or weak pointers (for smart pointer) internally. + * This type of registry is used only on the compute node side, where the Session class own all objects. + * On the host side, this class cannot be used currently as there is no object owner. + * + * \date 2013-10-22 + * \author Philipp Kegel + */ + +#ifndef SMARTCLOBJECTREGISTRY_H_ +#define SMARTCLOBJECTREGISTRY_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace detail { + +template +class RegistryValue { +public: + typedef T Type; + + static Type put(T& value) { return value; } + static T get(Type value) { return value; } +}; + +template +class RegistryValue> { +public: + typedef std::weak_ptr Type; + + static Type put(std::shared_ptr& value) { return std::weak_ptr(value); } + static std::shared_ptr get(const Type& value) { return value.lock(); } +}; + +/* ****************************************************************************/ + +template +class Registry { +public: + void bind( + dcl::object_id id, + T& objectPtr) { + _objects.insert(std::make_pair(id, RegistryValue::put(objectPtr))); + } + + void unbind( + dcl::object_id id) { + _objects.erase(id); + } + + T lookup( + dcl::object_id id) const { + auto i = _objects.find(id); + return (i == std::end(_objects)) ? T() : RegistryValue::get(i->second); + } + + void getIDs( + std::vector& ids) const { + ids.clear(); + for (auto entry : _objects) { + ids.push_back(entry.first); + } + } + +private: + std::map::Type> _objects; +}; + +} /* namespace detail */ + +/* ****************************************************************************/ + +/*! + * \brief A lookup facility for obtaining objects by their associated ID. + * + * It is the central resolver for object IDs. + */ +class SmartCLObjectRegistry: + private detail::Registry>, + private detail::Registry>, + private detail::Registry>, + private detail::Registry, + private detail::Registry>, + private detail::Registry>, + private detail::Registry> { +public: + SmartCLObjectRegistry(); + virtual ~SmartCLObjectRegistry(); + + /*! + * \brief Associates an ID with an object. + * + * \param[in] id the ID to assign + * \param[in] objectPtr the object to assign + */ + template + void bind( + dcl::object_id id, + T& objectPtr) { + detail::Registry::bind(id, objectPtr); + } + + /*! + * \brief Delete the association of the specified ID. + * + * \param[in] id the ID which association should be deleted + */ + template + void unbind(dcl::object_id id) { + detail::Registry::unbind(id); + } + + void unbindMemory( + dcl::object_id id); + + /*! + * \brief Looks up the object that is associated with the specified ID. + * + * \param[in] id the ID of the object to look up + * \return the object associated with ID, or \c NULL if no object is associated with id + */ + template + T lookup(dcl::object_id id) const { + return detail::Registry::lookup(id); + } + + template + void lookup( + const std::vector& ids, + std::vector& objects) const { + objects.clear(); + objects.reserve(ids.size()); + + for (auto id : ids) { + objects.push_back(detail::Registry::lookup(id)); + } + } + + std::shared_ptr lookupMemory( + dcl::object_id id) const; + + template + void getIDs( + std::vector& ids) const { + detail::Registry::getIDs(ids); + } +}; + +} /* namespace dclasio */ + +#endif /* SMARTCLOBJECTREGISTRY_H_ */ diff --git a/dclasio/src/dclasio/comm/CLEventProcessor.cpp b/dclasio/src/dclasio/comm/CLEventProcessor.cpp new file mode 100644 index 0000000..3a359b5 --- /dev/null +++ b/dclasio/src/dclasio/comm/CLEventProcessor.cpp @@ -0,0 +1,298 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLEventProcessor.cpp + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#include "CLEventProcessor.h" + +#include "../CommunicationManagerImpl.h" +#include "../ComputeNodeCommunicationManagerImpl.h" +#include "../ComputeNodeImpl.h" +#include "../HostImpl.h" +#include "../SmartCLObjectRegistry.h" + +#include +#include "../message/ContextErrorMessage.h" +#include +#include "../message/ProgramBuildMessage.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +/* **************************************************************************** + * Host side event processor + ******************************************************************************/ + +CLComputeNodeEventProcessor::CLComputeNodeEventProcessor( + const CommunicationManagerImpl& communicationManager, + const dcl::CLObjectRegistry& objectRegistry) : + _communicationManager(communicationManager), _objectRegistry(objectRegistry) { + // Message dispatcher must be initialized before the worker thread is created + _worker = std::thread(&CLComputeNodeEventProcessor::run, this); +} + +CLComputeNodeEventProcessor::~CLComputeNodeEventProcessor() { + // interrupt blocking queue to stop thread + _taskList.interrupt(); + if (_worker.joinable()) _worker.join(); +} + +void CLComputeNodeEventProcessor::run() { + try { + // wait for and dispatch execution status changes + while (true) { + _taskList.front()(); + _taskList.pop(); + } + } catch (const dcl::ThreadInterrupted&) { + // task queue has been interrupted + } +} + +void CLComputeNodeEventProcessor::contextError( + const message::ContextErrorMessage& notification) const { + auto contextListener = _objectRegistry.lookup(notification.contextId); + if (contextListener) { + contextListener->onError(notification.errorInfo.c_str(), + notification.privateInfo.value(), notification.privateInfo.size()); + } else { + dcl::util::Logger << dcl::util::Error + << "Context listener not found (ID=" << notification.contextId + << ')' << std::endl; + } +} + +void CLComputeNodeEventProcessor::executionStatusChanged( + const message::CommandExecutionStatusChangedMessage& notification) { + auto commandListener = _objectRegistry.lookup(notification.commandId()); + if (commandListener) { + // pass function call to worker thread + _taskList.push( + std::bind(&dcl::CommandListener::onExecutionStatusChanged, + commandListener, notification.status())); + } else { + dcl::util::Logger << dcl::util::Error + << "Command listener not found (command ID=" << notification.commandId() + << ')' << std::endl; + } +} + +void CLComputeNodeEventProcessor::synchronizeEvent( + const message::EventSynchronizationMessage& notification, + dcl::Process& process) const { + auto synchronizationlistener = _objectRegistry.lookup(notification.commandId()); + if (synchronizationlistener) { + synchronizationlistener->onSynchronize(process); + } else { + dcl::util::Logger << dcl::util::Error + << "Synchronization listener not found (command ID=" << notification.commandId() + << ')' << std::endl; + } +} + +void CLComputeNodeEventProcessor::programBuildComplete( + const message::ProgramBuildMessage& notification) const { + auto programBuildListener = _objectRegistry.lookup(notification.programBuildId); + if (programBuildListener) { + std::vector devices; + std::vector buildStatus; + + /* TODO Lookup devices from notification.deviceIds() */ + + programBuildListener->onComplete(devices, notification.buildStatus); + } else { + dcl::util::Logger << dcl::util::Error + << "Program build listener not found (ID=" << notification.programBuildId + << ')' << std::endl; + } +} + +bool CLComputeNodeEventProcessor::dispatch( + const message::Message& message, + dcl::process_id pid) { + ComputeNodeImpl *computeNode = nullptr; + + switch (message.get_type()) { + case message::ContextErrorMessage::TYPE: + dcl::util::Logger << dcl::util::Debug + << "Received context error message from compute node" << std::endl; + contextError( + static_cast(message)); + break; + + case message::CommandExecutionStatusChangedMessage::TYPE: + dcl::util::Logger << dcl::util::Debug + << "Received command execution status changed message from compute node" << std::endl; + executionStatusChanged( + static_cast(message)); + break; + + case message::EventSynchronizationMessage::TYPE: + dcl::util::Logger << dcl::util::Debug + << "Received event synchronization message from compute node" << std::endl; + + computeNode = _communicationManager.get_compute_node(pid); + assert(computeNode && "No host for event"); + if (!computeNode) + return false; + + synchronizeEvent( + static_cast(message), + *computeNode); + break; + + case message::ProgramBuildMessage::TYPE: + dcl::util::Logger << dcl::util::Debug + << "Received program build message" << std::endl; + programBuildComplete( + static_cast(message)); + break; + + default: // unknown message + return false; + } + + return true; +} + +/* **************************************************************************** + * Compute node side event processor + ******************************************************************************/ + +CLHostEventProcessor::CLHostEventProcessor( + const ComputeNodeCommunicationManagerImpl& communicationManager) : + _communicationManager(communicationManager) { } + +SmartCLObjectRegistry& CLHostEventProcessor::getObjectRegistry( + HostImpl& host) const { + /* TODO Do not make registry a member of host */ + return host.objectRegistry(); +} + +void CLHostEventProcessor::executionStatusChanged( + const message::CommandExecutionStatusChangedMessage& notification, + HostImpl& host) const { + auto event = getObjectRegistry(host).lookup>(notification.commandId()); + if (event) { + event->onExecutionStatusChanged(notification.status()); + } else { + dcl::util::Logger << dcl::util::Error + << "Event not found (command ID=" << notification.commandId() + << ')' << std::endl; + } +} + +void CLHostEventProcessor::synchronizeEvent( + const message::EventSynchronizationMessage& notification, + HostImpl& host) const { + auto event = getObjectRegistry(host).lookup>(notification.commandId()); + if (event) { + event->onSynchronize(host); + } else { + dcl::util::Logger << dcl::util::Error + << "Event not found (command ID=" << notification.commandId() + << ')' << std::endl; + } +} + +bool CLHostEventProcessor::dispatch( + const message::Message& message, + dcl::process_id pid) { + HostImpl *host = _communicationManager.get_host(pid); + assert(host && "No host for event"); + if (!host) + return false; + + switch (message.get_type()) { + case message::CommandExecutionStatusChangedMessage::TYPE: + dcl::util::Logger << dcl::util::Debug + << "Received command execution status changed message from host" << std::endl; + executionStatusChanged( + static_cast(message), *host); + break; + + case message::EventSynchronizationMessage::TYPE: + dcl::util::Logger << dcl::util::Debug + << "Received event synchronization message from host" << std::endl; + synchronizeEvent( + static_cast(message), *host); + break; + + default: // unknown message + return false; + } + + return true; +} + +} /* namespace comm */ + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/comm/CLEventProcessor.h b/dclasio/src/dclasio/comm/CLEventProcessor.h new file mode 100644 index 0000000..6fdc016 --- /dev/null +++ b/dclasio/src/dclasio/comm/CLEventProcessor.h @@ -0,0 +1,207 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLEventProcessor.h + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#ifndef CLEVENTPROCESSOR_H_ +#define CLEVENTPROCESSOR_H_ + +#include +#include + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { + +class ComputeNodeCommunicationManagerImpl; +class CommunicationManagerImpl; +class HostImpl; +class SmartCLObjectRegistry; + +namespace message { + +class ContextErrorMessage; +class Message; +class ProgramBuildMessage; + +} /* namespace message */ + +/* ****************************************************************************/ + +namespace comm { + +/*! + * \brief A processor for incoming application-level events. + */ +class CLEventProcessor { +public: + virtual ~CLEventProcessor() { } + + virtual bool dispatch( + const message::Message& message, + dcl::process_id pid) = 0; +}; + +/* ****************************************************************************/ + +/*! + * \brief A processor for incoming application-level events from compute nodes. + * + * This processor is used on the host! It is called 'CLComputeNodeEventProcessor' + * as it processes compute node event, i.e., events from compute nodes. + * + * This class should become the only implementation of an event processor. + * Due to implementation issues of ID generation (each host uses its own ID + * range) it currently has to be distinguished from event procesors used on + * the compute node side. + * + * \see CLHostEventProcessor + */ +class CLComputeNodeEventProcessor: public CLEventProcessor { +public: + /* A task is a nullary function */ + typedef std::function Task; + + CLComputeNodeEventProcessor( + const CommunicationManagerImpl& communicationManager, + const dcl::CLObjectRegistry& objectregistry); + virtual ~CLComputeNodeEventProcessor(); + + void run(); + + bool dispatch( + const message::Message& message, + dcl::process_id pid); + +private: + void contextError( + const message::ContextErrorMessage& notification) const; + + void executionStatusChanged( + const message::CommandExecutionStatusChangedMessage& notification); + + /*! + * \brief Callback for an incoming event synchronization request + * + * \param[in] notification the synchronization request + * \param[in] process the process that requested the synchronization + */ + void synchronizeEvent( + const message::EventSynchronizationMessage& notification, + dcl::Process& process) const; + + void programBuildComplete( + const message::ProgramBuildMessage& notification) const; + + const CommunicationManagerImpl& _communicationManager; + const dcl::CLObjectRegistry& _objectRegistry; //!< Registry for application objects + + dcl::BlockingQueue _taskList; //!< Task list for worker thread + + std::thread _worker; //!< Worker thread +}; + +/* ****************************************************************************/ + +/*! + * \brief A processor for incoming application-level events from hosts. + * + * This processor is used on compute nodes! It is called 'CLHostEventProcessor' + * as it processes host events, i.e., events from the host. + * + * Event messages from hosts have to be processed differently as the IDs within + * these messages refer to a particular host and, thus, are not unique if + * multiple hosts are connected to a compute nodes. + * Hence, a different event processor is required for each host that only + * processes event messages it received from this associated host. + * + * In future version of dOpenCL, UUIDs could be used to assign globally unique + * IDs to objects, such that an event processor does not have to consider the + * event source to resolve these IDs. Then, CLHostEventProcessor and + * CLComputeNodeEventProcessor can be merged into CLEventProcessor. + */ +class CLHostEventProcessor: public CLEventProcessor { +public: + CLHostEventProcessor( + const ComputeNodeCommunicationManagerImpl& communicationManager); + + bool dispatch( + const message::Message& message, + dcl::process_id pid); + +private: + SmartCLObjectRegistry& getObjectRegistry( + HostImpl& host) const; + + void executionStatusChanged( + const message::CommandExecutionStatusChangedMessage& notification, + HostImpl& host) const; + + /*! + * \brief Callback for an incoming event synchronization request + * + * \param[in] notification the synchronization request + * \param[in] host the host that requested the synchronization + */ + void synchronizeEvent( + const message::EventSynchronizationMessage& notification, + HostImpl& host) const; + + const ComputeNodeCommunicationManagerImpl& _communicationManager; +}; + +} /* namespace comm */ + +} /* namespace dclasio */ + +#endif /* CLEVENTPROCESSOR_H_ */ diff --git a/dclasio/src/dclasio/comm/CLRequestProcessor.cpp b/dclasio/src/dclasio/comm/CLRequestProcessor.cpp new file mode 100644 index 0000000..2e587c6 --- /dev/null +++ b/dclasio/src/dclasio/comm/CLRequestProcessor.cpp @@ -0,0 +1,1387 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLRequestProcessor.cpp + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#include "CLRequestProcessor.h" + +#include "../ComputeNodeCommunicationManagerImpl.h" +#include "../ComputeNodeImpl.h" +#include "../ContextListenerImpl.h" +#include "../HostImpl.h" +#include "../ProgramBuildListenerImpl.h" +#include "../SmartCLObjectRegistry.h" + +#include "../comm/DataTransferImpl.h" + +#include "../message/DeviceIDsResponse.h" +//#include "../message/DeviceInfosResponse.h" +#include "../message/GetDeviceIDs.h" +#include "../message/GetDeviceInfo.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +#include +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define __CL_ENABLE_EXCEPTIONS +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +/* A helper function to wrap new responses into a unique pointer */ +template +std::unique_ptr make_unique(Args&& ... args) { + return std::unique_ptr(new T(std::forward(args) ...)); +} + +} /* unnamed namespace */ + +/* ****************************************************************************/ + +namespace dclasio { +namespace comm { + +CLRequestProcessor::CLRequestProcessor( + ComputeNodeCommunicationManagerImpl& communicationManager) : + _communicationManager(communicationManager) { +} + +CLRequestProcessor::~CLRequestProcessor() { +} + +dcl::Session& CLRequestProcessor::getSession( + const HostImpl& host) const { + dcl::Session *session = _communicationManager.getDaemon()->getSession(host); + assert(session); + return *session; +} + +SmartCLObjectRegistry& CLRequestProcessor::getObjectRegistry( + HostImpl& host) const { + /* TODO Do not make registry a member of host */ + return host.objectRegistry(); +} + +void CLRequestProcessor::getComputeNodes( + const std::vector& computeNodeIds, + std::vector& computeNodes) const { + computeNodes.clear(); + + /* TODO Lookup (or create) compute nodes + * This operation can introduce new compute nodes to this compute node */ +} + +void CLRequestProcessor::getDevices( + const std::vector& deviceIds, + std::vector& devices) const { + /* TODO Resolve device IDs */ + _communicationManager.objectRegistry().lookup(deviceIds, devices); +} + +void CLRequestProcessor::getEventWaitList( + SmartCLObjectRegistry& registry, + const std::vector& eventIdWaitList, + std::vector>& eventWaitList) const { + eventWaitList.clear(); + eventWaitList.reserve(eventIdWaitList.size()); + + for (auto eventId : eventIdWaitList) { + auto event = registry.lookup>(eventId); + if (!event) { // event not found + throw cl::Error(CL_INVALID_EVENT_WAIT_LIST); + } + + eventWaitList.push_back(event); + } +} + +/******************************************************************************/ + +/* TODO Use unified registry for all processes + * A registry is provided by each host as each host assigns its own (and thus + * possibly identical) IDs to objects. Therefore, lookup host in compute node's + * connection manager, obtain registry, and lookup object in registry, rather + * than in the session. + * This also requires to register newly created objects in the registry within + * this class. + * + * Resolve an object ID: + HostImpl *host = _connectionManager.getHost(); + assert(host != nullptr); + host->objectRegistry().lookup...(...Id); + * Register a new object: + object = ...(...Id); + HostImpl *host = _connectionManager.getHost(); + assert(host != nullptr); + host->objectRegistry().register...(...Id, object); + * + * Object lookup is hard to implement, if the request is not sent by a host but + * rather another compute node or a device manager (formerly resource manager). + * This is, e.g., the case if events status changes are sent between compute + * nodes, directly. + * In these cases, it is not clear at which registry the objects are registered + * whose IDs are used by the compute node or device manager. + * + * Device IDs should not be resolved by a host's registry, as devices are not + * directly associated which a host but rather a platform. + * Solution idea: use connection manager to assign and resolve device IDs + * 1) add platform (cf. DeviceManager) to ComputeNodeCommunicationManager + * 2) Connection manager obtains list of all devices from platform and assigns + * IDs to all devices + */ + +#if 0 +/** + * @brief Obtain all platform information and return as compute node information. + */ +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::message::GetComputeNodeInfos& request, + HostImpl& host) { + try { + dcl::ComputeNode computeNode = _communicationManager.getComputeNode(); + + return make_unique(request, + computeNode.getInfo(), + computeNode.getInfo(), + computeNode.getInfo(), + computeNode.getInfo(), + computeNode.getInfo()); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} +#endif + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::GetDeviceIDs& request, + HostImpl& host) { + try { + std::vector deviceIDs; + + _communicationManager.objectRegistry().getIDs(deviceIDs); + + dcl::util::Logger << dcl::util::Info + << "Got device IDs" << std::endl; + + /* TODO Return list of (device ID, device type) pairs */ + return make_unique(request, deviceIDs); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::GetDeviceInfo& request, + HostImpl& host) { + dcl::Binary param; + + try { + auto device = _communicationManager.objectRegistry().lookup(request.deviceId); + + device->getInfo(request.paramName, param); + + dcl::util::Logger << dcl::util::Info + << "Got device info (device ID=" << request.deviceId + << ')' << std::endl; + + return make_unique(request, param.size(), param.value()); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateContext& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector computeNodes; + std::vector devices; + + try { + // TODO Read compute node IDs from message + getDevices(request.deviceIds(), devices); + + std::shared_ptr contextListener( + std::make_shared(request.contextId(), host)); + auto context = getSession(host).createContext( + host, computeNodes, devices, contextListener); + + registry.bind(request.contextId(), context); + + /* TODO Asynchronously connect to created compute nodes + * Return response when compute nodes have been connected */ + + dcl::util::Logger << dcl::util::Info + << "Context created (ID=" << request.contextId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::DeleteContext& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + getSession(host).releaseContext( + registry.lookup>(request.contextId())); + registry.unbind>(request.contextId()); + + dcl::util::Logger << dcl::util::Info + << "Context released (ID=" << request.contextId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateBuffer& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + cl_mem_flags hostPtrFlags = request.flags() & + (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR); + size_t size = request.size(); + std::unique_ptr host_ptr; + + if (hostPtrFlags) { + /* receive buffer data from host */ + host_ptr.reset(new unsigned char[size]); + if (!host_ptr) throw cl::Error(CL_OUT_OF_RESOURCES); + host.receiveData(size, host_ptr.get())->wait(); + } + + auto buffer = getSession(host).createBuffer( + registry.lookup>(request.contextId()), + request.flags(), request.size(), host_ptr.get()); + registry.bind(request.bufferId(), buffer); + + dcl::util::Logger << dcl::util::Info + << "Buffer created (ID=" << request.bufferId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::DeleteMemory& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + getSession(host).releaseMemObject( + registry.lookupMemory(request.memObjectId())); + registry.unbindMemory(request.memObjectId()); + + dcl::util::Logger << dcl::util::Info + << "Memory object released (ID=" << request.memObjectId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateCommandQueue& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + auto device = _communicationManager.objectRegistry().lookup(request.deviceId()); + + auto commandQueue = getSession(host).createCommandQueue( + registry.lookup>(request.contextId()), + device, + request.properties()); + registry.bind(request.commandQueueId(), commandQueue); + + dcl::util::Logger << dcl::util::Info + << "Command queue created (ID=" << request.commandQueueId() << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::DeleteCommandQueue& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + getSession(host).releaseCommandQueue( + registry.lookup>(request.commandQueueId())); + registry.unbind>(request.commandQueueId()); + + dcl::util::Logger << dcl::util::Info + << "Command queue released (ID=" << request.commandQueueId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateProgramWithSource& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::unique_ptr source; + size_t length = request.length(); + + /* Receive program sources */ + try { + source.reset(new char[length]); + host.receiveData(length, source.get())->wait(); // blocking receive + } catch (const std::bad_alloc&) { + return make_unique(request, CL_OUT_OF_RESOURCES); + } + + try { + auto program = getSession(host).createProgram( + registry.lookup>(request.contextId()), + source.get(), length); + registry.bind(request.programId(), program); + + dcl::util::Logger << dcl::util::Info + << "Program created from source (ID=" << request.programId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +#if 0 +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateProgramWithBinary& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::unique_ptr[]> strings; + size_t *lengths; + unsigned char **binaries; + VECTOR_CLASS binary_status; + + /* Receive program binaries */ + try { + strings.reset(new std::unique_ptr[lengths.size()]); + + for (unsigned int i = 0; i < lengths.size(); ++i) { + size_t length = lengths[i]; + + strings[i].reset(new unsigned char[length]); + void *binary = static_cast(strings[i].get()); + host.receiveData(length, binary)->wait(); // blocking receive + } + + /* DO NOT DELETE strings, as binaries hold pointers to strings */ + } catch (const std::bad_alloc&) { + return make_unique(request, CL_OUT_OF_RESOURCES); + } + + /* TODO Initialize lengths and binaries arguments for dcld::Session::createProgram */ + + try { + auto program = getSession(host).createProgram( + registry.lookup>(request.contextId()), + lengths, + binaries, + &binary_status); + registry.bind(request.programId(), program); + + dcl::util::Logger << dcl::util::Info + << "Program created from binaries (ID=" << request.programId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } + + /* Now strings may be deleted safely */ +} +#endif + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::DeleteProgram& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + getSession(host).releaseProgram( + registry.lookup>(request.programId())); + registry.unbind>(request.programId()); + + dcl::util::Logger << dcl::util::Info + << "Program released (ID=" << request.programId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::BuildProgram& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + auto program = registry.lookup>(request.programId()); + std::vector devices; + + getDevices(request.deviceIds(), devices); + + /* TODO Register program build listener; manage ID externally */ + std::shared_ptr programBuildListener( + std::make_shared(request.programBuildId(), host)); + program->build(devices, request.options().c_str(), programBuildListener); + + dcl::util::Logger << dcl::util::Info + << "Program build submitted (program ID=" << request.programId() + << ", build ID=" << request.programBuildId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err){ + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateKernel& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + auto kernel = getSession(host).createKernel( + registry.lookup>( + request.programId()), request.kernelName()); + registry.bind(request.kernelId(), kernel); + + dcl::util::Logger << dcl::util::Info + << "Kernel created (ID=" << request.kernelId() + << ", name=" << request.kernelName() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err){ + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateKernelsInProgram& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + auto kernels = getSession(host).createKernelsInProgram( + registry.lookup>(request.programId()), + request.kernelIds().size()); + + /* Register kernels */ + auto id = std::begin(request.kernelIds()); + auto kernel = std::begin(kernels); + while (id != std::end(request.kernelIds()) && kernel != std::end(kernels)) { + registry.bind(*id++, *kernel++); + } + + dcl::util::Logger << dcl::util::Info + << "Kernels in program created (program ID=" << request.programId() + << ", #kernels=" << kernels.size() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::DeleteKernel& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + getSession(host).releaseKernel( + registry.lookup>(request.kernelId())); + registry.unbind>(request.kernelId()); + + dcl::util::Logger << dcl::util::Info + << "Kernel released (ID=" << request.kernelId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::CreateEvent& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> memoryObjects; + + try { + /* Resolve memory object IDs */ + memoryObjects.reserve(request.memObjectIds().size()); + for (auto memObjectId : request.memObjectIds()) { + memoryObjects.push_back(registry.lookupMemory(memObjectId)); + } + + std::shared_ptr event = getSession(host).createEvent( + request.eventId(), + registry.lookup>(request.contextId()), + memoryObjects); + registry.bind(request.eventId(), event); + + dcl::util::Logger << dcl::util::Info + << "Event created (ID=" << request.eventId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::DeleteEvent& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + getSession(host).releaseEvent( + registry.lookup>(request.eventId())); + registry.unbind>(request.eventId()); + + dcl::util::Logger << dcl::util::Info + << "Event released (ID=" << request.eventId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::GetEventProfilingInfos& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + cl_ulong received, queued, submit, start, end; + + auto event = registry.lookup>(request.eventId()); + + event->getProfilingInfo(CL_PROFILING_COMMAND_RECEIVED_WWU, received); + event->getProfilingInfo(CL_PROFILING_COMMAND_QUEUED, queued); + event->getProfilingInfo(CL_PROFILING_COMMAND_SUBMIT, submit); + event->getProfilingInfo(CL_PROFILING_COMMAND_START, start); + event->getProfilingInfo(CL_PROFILING_COMMAND_END, end); + + dcl::util::Logger << dcl::util::Info + << "Got event profiling info (ID=" << request.eventId() << ')' + << std::endl; + + return make_unique( + request, received, queued, submit, start, end); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::GetKernelInfo& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + dcl::Binary param; + + registry.lookup>(request.kernelId())->getInfo( + request.paramName(), param); + + dcl::util::Logger << dcl::util::Info + << "Got kernel info (ID=" << request.kernelId() << ')' + << std::endl; + + return make_unique(request, param.size(), param.value()); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::GetKernelWorkGroupInfo& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + dcl::Binary param; + + try { + auto device = _communicationManager.objectRegistry().lookup(request.deviceId()); + + registry.lookup>(request.kernelId())->getWorkGroupInfo( + device, request.paramName(), param); + + dcl::util::Logger << dcl::util::Info + << "Got kernel work group info (kernel ID=" << request.kernelId() + << ", device ID=" << request.deviceId() + << ')' << std::endl; + + return make_unique( + request, param.size(), param.value()); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueCopyBuffer& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr copyBuffer; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueCopyBuffer( + registry.lookup>(request.srcBufferId()), + registry.lookup>(request.dstBufferId()), + request.srcOffset(), request.dstOffset(), request.cb(), + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? ©Buffer : nullptr) + ); + + if (copyBuffer) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(copyBuffer); + registry.bind(request.commandId(), copyBuffer); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued copy buffer (command queue ID=" << request.commandQueueId() + << ", src buffer ID=" << request.srcBufferId() + << ", dst buffer ID=" << request.dstBufferId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueWriteBuffer& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr writeBuffer; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueWriteBuffer( + registry.lookup>(request.bufferId()), + request.blocking(), request.offset(), + request.cb(), + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &writeBuffer : nullptr) + ); + + if (writeBuffer) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(writeBuffer); + registry.bind(request.commandId(), writeBuffer); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued data upload to buffer (command queue ID=" + << request.commandQueueId() << ", buffer ID=" << request.bufferId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueReadBuffer& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr readBuffer; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueReadBuffer( + registry.lookup>(request.bufferId()), + request.blocking(), request.offset(), + request.cb(), + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &readBuffer : nullptr) + ); + + if (readBuffer) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(readBuffer); + registry.bind(request.commandId(), readBuffer); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued data download from buffer (command queue ID=" + << request.commandQueueId() << ", buffer ID=" << request.bufferId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueBroadcastBuffer& request, + HostImpl& host) { + try { + /* TODO Implement and call dcl::CommandQueue::enqueueBroadcastBuffer */ + assert(!"dcl::CommandQueue::enqueueBroadcastBuffer not implemented"); + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueReduceBuffer& request, + HostImpl& host) { + try { + /* TODO Implement and call dcl::CommandQueue::enqueueReduceBuffer */ + assert(!"dcl::CommandQueue::enqueueReduceBuffer not implemented"); + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueNDRangeKernel& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr ndRangeKernel; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueNDRangeKernel( + registry.lookup>(request.kernelId()), + request.offset(), request.global(), request.local(), + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &ndRangeKernel : nullptr) + ); + + if (ndRangeKernel) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(ndRangeKernel); + registry.bind(request.commandId(), ndRangeKernel); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued ND range kernel (command queue ID=" << request.commandQueueId() + << ", kernel ID=" << request.kernelId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueBarrier& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr barrier; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueBarrier( + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &barrier : nullptr) + ); + + if (barrier) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(barrier); + registry.bind(request.commandId(), barrier); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued barrier (command queue ID=" << request.commandQueueId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueWaitForEvents& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventList; + + try { + /* Lookup events of event list + * Unlike other enqueued commands, wait for events throws CL_INVALID_EVENT + * rather than CL_INVALID_EVENT_WAIT_LIST if the event list contains an + * invalid event. Moreover, the event list must not contain user events */ + eventList.reserve(request.eventIdList().size()); + for (auto eventId : request.eventIdList()) { + eventList.push_back(registry.lookup>(eventId)); + } + + registry.lookup>(request.commandQueueId())->enqueueWaitForEvents( + eventList); + + dcl::util::Logger << dcl::util::Info + << "Enqueued wait for events (command queue ID=" << request.commandQueueId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueMapBuffer& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr mapBuffer; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueMapBuffer( + registry.lookup>(request.bufferId()), + request.blocking(), request.mapFlags(), + request.offset(), request.cb(), + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &mapBuffer : nullptr) + ); + + if (mapBuffer) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(mapBuffer); + registry.bind(request.commandId(), mapBuffer); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued map buffer (command queue ID=" << request.commandQueueId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueUnmapBuffer& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr unmapBuffer; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueUnmapBuffer( + registry.lookup>(request.bufferId()), + request.mapFlags(), + request.offset(), request.cb(), + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &unmapBuffer : nullptr) + ); + + if (unmapBuffer) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(unmapBuffer); + registry.bind(request.commandId(), unmapBuffer); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued unmap buffer (command queue ID=" << request.commandQueueId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::EnqueueMarker& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + std::vector> eventWaitList; + std::shared_ptr marker; + + try { + getEventWaitList(registry, request.eventIdWaitList(), eventWaitList); + + registry.lookup>(request.commandQueueId())->enqueueMarker( + (eventWaitList.empty() ? nullptr : &eventWaitList), + request.commandId(), + (request.event() ? &marker : nullptr) + ); + + if (marker) { // an event should be associated with this command + /* FIXME Add event to session automatically */ + getSession(host).addEvent(marker); + registry.bind(request.commandId(), marker); + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued marker (command queue ID=" << request.commandQueueId() + << ", command ID=" << request.commandId() + << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::FinishRequest& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + /* TODO Finish command queue asynchronously */ + registry.lookup>(request.commandQueueId())->finish(); + + dcl::util::Logger << dcl::util::Info + << "Finished command queue (ID=" << request.commandQueueId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::FlushRequest& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + registry.lookup>(request.commandQueueId())->flush(); + + dcl::util::Logger << dcl::util::Info + << "Flushed command queue (ID=" << request.commandQueueId() << ')' + << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::SetKernelArgMemObject& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + auto kernel = registry.lookup>(request.kernelId()); + + if (request.argValue() == nullptr) { + kernel->setArg(request.argIndex(), request.argSize()); + } else { + auto memory = registry.lookupMemory( + *reinterpret_cast(request.argValue())); + kernel->setArg(request.argIndex(), memory); + } + + dcl::util::Logger << dcl::util::Info + << "Kernel argument set (ID=" << request.kernelId() << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +template<> +std::unique_ptr CLRequestProcessor::execute( + const message::SetKernelArgBinary& request, + HostImpl& host) { + SmartCLObjectRegistry& registry = getObjectRegistry(host); + + try { + registry.lookup>(request.kernelId())->setArg( + request.argIndex(), request.argSize(), request.argValue()); + + dcl::util::Logger << dcl::util::Info + << "Kernel argument set (ID=" << request.kernelId() << ')' << std::endl; + + return make_unique(request); + } catch (const cl::Error& err) { + return make_unique(request, err.err()); + } +} + +bool CLRequestProcessor::dispatch( + const message::Request& request, + dcl::process_id pid) { + std::unique_ptr response; + + HostImpl *host = _communicationManager.get_host(pid); + /* TODO Discard request from unknown processes + * Only processes that have identified ('connected') themselves as host + * or possibly also compute nodes are allowed to issue requests. */ + assert(host && "No host for request"); + if (!host) + return false; + + /* + * Dispatch request + */ + switch (request.get_type()) { + + /* Requests sent by any dOpenCL node */ + case message::GetDeviceIDs::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::GetDeviceInfo::TYPE: + response = execute( + static_cast(request), *host); + break; + + /* Request sent by hosts */ + case message::CreateContext::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::DeleteContext::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::DeleteMemory::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::CreateBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::CreateCommandQueue::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::DeleteCommandQueue::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueBarrier::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueBroadcastBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueCopyBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueMapBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueMarker::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueNDRangeKernel::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueWriteBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueReadBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueReduceBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::EnqueueUnmapBuffer::TYPE: + response = execute( + static_cast(request), *host); + break; +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + case message::EnqueueWaitForEvents::TYPE: + response = execute( + static_cast(request), *host); + break; +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + case message::FinishRequest::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::FlushRequest::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::CreateProgramWithSource::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::DeleteProgram::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::BuildProgram::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::CreateKernel::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::CreateKernelsInProgram::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::DeleteKernel::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::CreateEvent::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::DeleteEvent::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::GetKernelInfo::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::GetKernelWorkGroupInfo::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::GetEventProfilingInfos::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::SetKernelArgMemObject::TYPE: + response = execute( + static_cast(request), *host); + break; + case message::SetKernelArgBinary::TYPE: + response = execute( + static_cast(request), *host); + break; + + default: // unknown request + return false; + } + + // a response should have been created to answer a request + assert(response && "No response"); + if (response) { + host->sendMessage(*response); + } + + return true; +} + +} /* namespace comm */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/comm/CLRequestProcessor.h b/dclasio/src/dclasio/comm/CLRequestProcessor.h new file mode 100644 index 0000000..751da67 --- /dev/null +++ b/dclasio/src/dclasio/comm/CLRequestProcessor.h @@ -0,0 +1,126 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLRequestProcessor.h + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#ifndef CLREQUESTPROCESSOR_H_ +#define CLREQUESTPROCESSOR_H_ + +#include +#include +#include +#include + +#include +#include + +namespace dclasio { + +/* forward declaration */ +class ComputeNodeCommunicationManagerImpl; +class HostImpl; +class SmartCLObjectRegistry; + +namespace message { + +class Request; +class Response; + +} // namespace message + +/* ****************************************************************************/ + +namespace comm { + +/** + * @brief A processor for incoming command requests. + * + * Requests are unmarshalled and forwarded to the application. + */ +class CLRequestProcessor { +public: + CLRequestProcessor( + ComputeNodeCommunicationManagerImpl& communicationManager); + virtual ~CLRequestProcessor(); + + bool dispatch( + const message::Request& request, + dcl::process_id pid); + +private: + dcl::Session& getSession( + const HostImpl& host) const; + SmartCLObjectRegistry& getObjectRegistry( + HostImpl& host) const; + void getComputeNodes( + const std::vector& computeNodeIds, + std::vector& computeNodes) const; + void getDevices( + const std::vector& deviceIds, + std::vector& devices) const; + void getEventWaitList( + SmartCLObjectRegistry& registry, + const std::vector& eventIdWaitList, + std::vector>& eventWaitList) const; + + /** + * @brief Execute a given request + * + * A request is unmarshalled and an appropriate method is called. + * The method's output is marshalled into a response. + * + * @param[in] request the request + * @param[in] host the requesting host + * @return the response + */ + template + std::unique_ptr execute( + const T& request, + HostImpl& host); + + ComputeNodeCommunicationManagerImpl& _communicationManager; +}; + +} /* namespace comm */ + +} /* namespace dclasio */ + +#endif /* CLREQUESTPROCESSOR_H_ */ diff --git a/dclasio/src/dclasio/comm/CLResponseProcessor.cpp b/dclasio/src/dclasio/comm/CLResponseProcessor.cpp new file mode 100644 index 0000000..fb723c9 --- /dev/null +++ b/dclasio/src/dclasio/comm/CLResponseProcessor.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLResponseProcessor.cpp + * + * \date 2014-05-01 + * \author Philipp Kegel + */ + +#include "CLResponseProcessor.h" + +#include "../CommunicationManagerImpl.h" +#include "../ComputeNodeImpl.h" + +#include "../message/DeviceIDsResponse.h" +#include "../message/DeviceInfosResponse.h" + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +namespace dclasio { +namespace comm { + +CLResponseProcessor::CLResponseProcessor( + CommunicationManagerImpl& connectionManager) : + _communicationManager(connectionManager) { +} + +CLResponseProcessor::~CLResponseProcessor() { +} + +bool CLResponseProcessor::dispatch( + const message::Response& message, + dcl::process_id pid) { + std::unique_ptr response; + + ComputeNodeImpl *computeNode = _communicationManager.get_compute_node(pid); + assert(computeNode && "No compute node for response"); + if (!computeNode) + return false; + + switch (message.get_type()) { + // command responses + case message::DefaultResponse::TYPE: + response.reset(new message::DefaultResponse( + static_cast(message))); + break; + case message::DeviceIDsResponse::TYPE: + response.reset(new message::DeviceIDsResponse( + static_cast(message))); + break; + case message::DeviceInfosResponse::TYPE: + response.reset(new message::DeviceInfosResponse( + static_cast(message))); + break; + case message::ErrorResponse::TYPE: + response.reset(new message::ErrorResponse( + static_cast(message))); + break; + case message::EventProfilingInfosReponse::TYPE: + response.reset(new message::EventProfilingInfosReponse( + static_cast(message))); + break; + case message::InfoResponse::TYPE: + response.reset(new message::InfoResponse( + static_cast(message))); + break; + + default: // unknown message + return false; + } + + assert(response && "No response"); + if (response) { + // move response into the response buffer associated with sender + computeNode->responseBuffer().put(std::move(response)); + dcl::util::Logger << dcl::util::Verbose + << "Received response from compute node" << std::endl; + } + + return true; +} + +} /* namespace comm */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/comm/CLResponseProcessor.h b/dclasio/src/dclasio/comm/CLResponseProcessor.h new file mode 100644 index 0000000..17eea3b --- /dev/null +++ b/dclasio/src/dclasio/comm/CLResponseProcessor.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CLResponseProcessor.h + * + * \date 2014-05-01 + * \author Philipp Kegel + */ + +#ifndef CLRESPONSEPROCESSOR_H_ +#define CLRESPONSEPROCESSOR_H_ + +#include + +namespace dclasio { + +/* forward declaration */ +class CommunicationManagerImpl; + +namespace message { + +class Response; + +} // namespace message + +/* ****************************************************************************/ + +namespace comm { + +/** + * @brief A processor for dispatching incoming command responses into response buffers + */ +class CLResponseProcessor { +public: + CLResponseProcessor( + CommunicationManagerImpl& communicationManager); + virtual ~CLResponseProcessor(); + + bool dispatch( + const message::Response& response, + dcl::process_id pid); + +private: + CommunicationManagerImpl& _communicationManager; +}; + +} /* namespace comm */ + +} /* namespace dclasio */ + +#endif /* CLRESPONSEPROCESSOR_H_ */ diff --git a/dclasio/src/dclasio/comm/ConnectionListener.h b/dclasio/src/dclasio/comm/ConnectionListener.h new file mode 100644 index 0000000..1901636 --- /dev/null +++ b/dclasio/src/dclasio/comm/ConnectionListener.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ConnectionListener.h + * + * \date 2014-04-06 + * \author Philipp Kegel + */ + +#ifndef CONNECTIONLISTENER_H_ +#define CONNECTIONLISTENER_H_ + +#include "../ProcessImpl.h" + +#include + +namespace dclasio { +namespace comm { + +class DataStream; +class message_queue; + +/* ****************************************************************************/ + +/*! + * Connection listener API + */ +class connection_listener { +public: + virtual ~connection_listener() { } + + virtual bool approve_message_queue( + ProcessImpl::Type process_type, + dcl::process_id process_id) = 0; + + virtual void message_queue_connected( + message_queue& msgq, + ProcessImpl::Type process_type, + dcl::process_id process_id) = 0; + + virtual void message_queue_disconnected( + message_queue& msgq) = 0; + + virtual bool approve_data_stream( + dcl::process_id process_id) = 0; + + virtual void data_stream_connected( + DataStream& dataStream, + dcl::process_id process_id) = 0; +}; + +} /* namespace comm */ +} /* namespace dclasio */ + +#endif /* CONNECTIONLISTENER_H_ */ diff --git a/dclasio/src/dclasio/comm/DataDispatcher.cpp b/dclasio/src/dclasio/comm/DataDispatcher.cpp new file mode 100644 index 0000000..46eb898 --- /dev/null +++ b/dclasio/src/dclasio/comm/DataDispatcher.cpp @@ -0,0 +1,243 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DataDispatcher.cpp + * + * \date 2014-03-07 + * \author Philipp Kegel + */ + +#include "DataDispatcher.h" + +#include "../DCLAsioTypes.h" + +#include "ConnectionListener.h" +#include "DataStream.h" +#include "DataTransferImpl.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +DataDispatcher::DataDispatcher( + dcl::process_id pid) : _work(_io_service), _pid(pid) { +} + +DataDispatcher::~DataDispatcher() { + stop(); +} + +DataStream * DataDispatcher::create_data_stream( + const endpoint_type& endpoint) { + // create socket + auto socket(std::make_shared(_io_service)); + return add_data_stream(new DataStream(socket, endpoint)); +} + +void DataDispatcher::destroy_data_stream( + DataStream *data_stream) { + std::lock_guard lock(_mutex); + // remove data stream from list; implicitly calls destructor + _data_streams.remove_if([data_stream](const std::unique_ptr& entry){ + return entry.get() == data_stream; }); +} + +void DataDispatcher::add_connection_listener( + connection_listener& listener) { + std::lock_guard lock(_mutex); + _connection_listeners.insert(&listener); +} + +void DataDispatcher::remove_connection_listener( + connection_listener& listener) { + std::lock_guard lock(_mutex); + _connection_listeners.erase(& listener); +} + +void DataDispatcher::bind( + const endpoint_type& endpoint) { + // create server socket + _acceptor.reset(new boost::asio::ip::tcp::acceptor(_io_service)); + _acceptor->open(boost::asio::ip::tcp::v4()); + _acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + _acceptor->bind(endpoint); +} + +void DataDispatcher::start() { + if (_acceptor) { + try { + _acceptor->listen(); + + // initiate accept loop + start_accept(); + } catch (const boost::system::system_error& err) { + dcl::util::Logger << dcl::util::Error + << "Could not start data stream acceptor: " + << err.what() + << std::endl; + } + } + + /* start worker thread + * use lambda to resolve overloaded boost::asio::io_service::run */ + _worker = std::thread([this](){ _io_service.run(); }); +} + +void DataDispatcher::stop() { + _io_service.stop(); + if (_worker.joinable()) _worker.join(); +} + +void DataDispatcher::start_accept() { + auto socket(std::make_shared(_io_service)); + // await incoming data stream connection + _acceptor->async_accept(*socket, + [this, socket](const boost::system::error_code& ec){ + handle_accept(socket, ec); }); +} + +void DataDispatcher::handle_accept( + std::shared_ptr socket, + const boost::system::error_code& ec) { + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not accept data stream: " + << ec.message() << std::endl; + return; + } + + auto buf(std::make_shared()); + buf->resize(sizeof(dcl::process_id) + 2); + + // await authentication request from incoming data stream + boost::asio::async_read( + *socket, + boost::asio::buffer(buf->begin(), buf->size()), + [this, socket, buf](const boost::system::error_code& ec, size_t bytes_transferred) { + handle_approval(socket, buf, ec, bytes_transferred); }); + + start_accept(); // await another incoming data stream connection +} + +void DataDispatcher::handle_approval( + std::shared_ptr socket, + std::shared_ptr buf, + const boost::system::error_code& ec, + size_t bytes_transferred) { + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not approve data stream: " + << ec.message() << std::endl; + return; + } + + dcl::process_id pid; + uint8_t proc_type; // process type + uint8_t proto; // protocol (must be data stream) + *buf >> pid >> proc_type >> proto; + // TODO Ensure pid != 0 + /* TODO Ensure process type + ProcessImpl::Type process_type = static_cast(proc_type); + */ + // TODO Ensure data stream protocol + + // request connection approval + std::unique_lock lock(_mutex); + std::vector listeners( + std::begin(_connection_listeners), std::end(_connection_listeners)); + lock.unlock(); + bool approved = false; + for (auto listener : listeners) { + if (listener->approve_data_stream(pid)) { + approved = true; + break; + } + } + + if (approved) { + // data stream has been approved - keep it + auto dataStream = add_data_stream(new DataStream(socket)); + +#if USE_DATA_STREAM_RESPONSE + *buf << _pid; // signal approval: return own process ID + boost::asio::write(*socket, boost::asio::buffer(buf->begin(), buf->size())); +#endif + dcl::util::Logger << dcl::util::Verbose + << "Accepted data stream from process (pid=" << pid << ')' + << std::endl; + + for (auto listener : listeners) { + listener->data_stream_connected(*dataStream, pid); + } + } else { +#if USE_DATA_STREAM_RESPONSE + // signal reject: return process ID 0 + *buf << dcl::process_id(0); + boost::asio::write(*socket, boost::asio::buffer(buf->begin(), buf->size())); +#endif + dcl::util::Logger << dcl::util::Error + << "Rejected data stream from process (pid=" << pid << ')' + << std::endl; + } +} + +} // namespace comm + +} // namespace dclasio diff --git a/dclasio/src/dclasio/comm/DataDispatcher.h b/dclasio/src/dclasio/comm/DataDispatcher.h new file mode 100644 index 0000000..6a5aa51 --- /dev/null +++ b/dclasio/src/dclasio/comm/DataDispatcher.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DataDispatcher.h + * + * \date 2014-03-07 + * \author Philipp Kegel + */ + +#ifndef DATADISPATCHER_H_ +#define DATADISPATCHER_H_ + +#include "../DCLAsioTypes.h" + +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +class connection_listener; +class DataStream; + +/* ****************************************************************************/ + +/*! + * Manages the threads for process pending data transfers of all data streams + */ +class DataDispatcher { +public: + DataDispatcher( + dcl::process_id pid); + virtual ~DataDispatcher(); + + /*! + * \brief Creates a data stream that is processed by this data dispatcher + * Use destroyDataStream to destroy the data stream + * + * \param endpoint endpoint of the remote process + * \return a data stream + */ + DataStream * create_data_stream( + const endpoint_type& endpoint); + + /*! + * \brief Destroys a data stream that is processed by this data dispatcher + * + * \param[in] dataStream the data stream to destroy + */ + void destroy_data_stream( + DataStream *dataStream); + + void add_connection_listener( + connection_listener& listener); + void remove_connection_listener( + connection_listener& listener); + + void bind( + const endpoint_type& endpoint); + + void start(); + void stop(); + +private: + /*! + * \brief Asynchronously start listening for an incoming data stream + */ + void start_accept(); + + /*! + * \brief Callback for incoming data stream + * + * \param[in] socket socket of incoming data stream + * \param[in] ec error code + */ + void handle_accept( + std::shared_ptr socket, + const boost::system::error_code& ec); + + /*! + * \brief Callback for data stream handshake + * This method authenticates an incoming data stream and either notifies + * registered connection listeners, or rejects and closes the data stream. + * + * \param[in] socket socket of incoming data stream + * \param[in] buf identification received from data stream + * \param[in] ec error code + * \param[in] bytes_transferred number of received bytes + */ + void handle_approval( + std::shared_ptr socket, + std::shared_ptr buf, + const boost::system::error_code& ec, + size_t bytes_transferred); + + /*! + * \brief Adds a data stream to this data dispatcher + * + * \param[in] args arguments for emplacing a unique pointer to the data stream + * \return a raw pointer to the added data stream + */ + template + DataStream * add_data_stream( + Args&& ... args) { + std::lock_guard lock(_mutex); + _data_streams.emplace_back(std::forward(args) ...); + return _data_streams.back().get(); + } + + boost::asio::io_service _io_service; + boost::asio::io_service::work _work; //!< work flag for I/O service + std::unique_ptr _acceptor; //!< server socket + + dcl::process_id _pid; + std::thread _worker; + + std::list> _data_streams; //!< data stream managed by this data dispatcher + std::unordered_set _connection_listeners; //!< connection listeners + std::mutex _mutex; //!< protects data stream and connection listener containers +}; + +} /* namespace comm */ + +} /* namespace dclasio */ + +#endif /* DATADISPATCHER_H_ */ diff --git a/dclasio/src/dclasio/comm/DataStream.cpp b/dclasio/src/dclasio/comm/DataStream.cpp new file mode 100644 index 0000000..824b24b --- /dev/null +++ b/dclasio/src/dclasio/comm/DataStream.cpp @@ -0,0 +1,245 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DataStream.cpp + * + * \date 2014-03-07 + * \author Philipp Kegel + */ + +#include "DataStream.h" + +#include "DataTransferImpl.h" + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +DataStream::DataStream( + const std::shared_ptr& socket) : + _socket(socket), _receiving(false), _sending(false) { + // TODO Ensure that socket is connected + _remote_endpoint = _socket->remote_endpoint(); +} + +DataStream::DataStream( + const std::shared_ptr& socket, + boost::asio::ip::tcp::endpoint remote_endpoint) : + _socket(socket), _remote_endpoint(remote_endpoint), _receiving(false), _sending(false) { + assert(!socket->is_open()); // socket must not be connect +} + +DataStream::~DataStream() { +} + +dcl::process_id DataStream::connect( + dcl::process_id pid) { + _socket->connect(_remote_endpoint); // connect socket to remote endpoint + + // send process ID to remote process via data stream + // TODO Encode local process type and data stream protocol + dcl::ByteBuffer buf; + buf << pid << uint8_t(0) << uint8_t(0); + boost::asio::write(*_socket, boost::asio::buffer(buf.begin(), buf.size())); + dcl::util::Logger << dcl::util::Verbose + << "Sent process identification message for data stream (pid=" << pid << ')' + << std::endl; + +#if USE_DATA_STREAM_RESPONSE + // receive response + buf.resize(sizeof(dcl::process_id)); + boost::asio::read(*_socket, boost::asio::buffer(buf.begin(), buf.size())); + buf >> pid; + dcl::util::Logger << dcl::util::Verbose + << "Received identification message response (pid=" << pid << ')' + << std::endl; +#endif + + return pid; +} + +void DataStream::disconnect() { + _socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); + _socket->close(); +} + +std::shared_ptr DataStream::read( + size_t size, void *ptr) { + auto read(std::make_shared(size, ptr)); + + std::unique_lock lock(_readq_mtx); + if ((_receiving)) { + _readq.push(read); + } else { + // start read loop + _receiving = true; + lock.unlock(); + + start_read(new readq_type({ read })); + } + + return read; +} + +std::shared_ptr DataStream::write( + size_t size, const void *ptr) { + auto write(std::make_shared(size, ptr)); + + std::unique_lock lock(_writeq_mtx); + if (_sending) { + _writeq.push(write); + } else { + // start write loop + _sending = true; + lock.unlock(); + + start_write(new writeq_type({ write })); + } + + return write; +} + +void DataStream::start_read( + readq_type *readq) { + /* TODO Pass readq by rvalue reference rather than by pointer + * This is currently not supported by lambdas (see comment in start_write) */ + assert(readq); // ouch! + if (readq->empty()) { + // pick new reads from the data stream's read queue + std::lock_guard lock(_readq_mtx); + if (_readq.empty()) { + _receiving = false; + delete readq; + return; // no more reads - exit read loop + } + _readq.swap(*readq); + } + // readq is non-empty now + + auto& read = readq->front(); + read->onStart(); + boost::asio::async_read( + *_socket, boost::asio::buffer(read->ptr(), read->size()), + [this, readq](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_read(readq, ec, bytes_transferred); }); +} + +void DataStream::handle_read( + readq_type *readq, + const boost::system::error_code& ec, + size_t bytes_transferred) { + // current read is first element in readq, so readq must be non-empty + assert(readq /* ouch! */ && !readq->empty()); + readq->front()->onFinish(ec, bytes_transferred); + readq->pop(); + + if (ec) { + // TODO Handle errors + } + + start_read(readq); // process remaining reads +} + +void DataStream::start_write( + writeq_type *writeq) { + /* TODO Pass writeq by rvalue reference rather than by pointer + * is currently not supported by lambdas (see comment below) */ + assert(writeq); // ouch! + if (writeq->empty()) { + // pick new writes from the data stream's write queue + std::lock_guard lock(_writeq_mtx); + if (_writeq.empty()) { + _sending = false; + delete writeq; + return; // no more writes - exit write loop + } + _writeq.swap(*writeq); + } + // writeq is non-empty now + + auto& write = writeq->front(); + write->onStart(); + /* TODO *Move* writeq through (i.e., into and out of) lambda capture + * In C++14 this should be possible by generalized lambda captures as follows: + boost::asio::async_write( + *_socket, boost::asio::buffer(write->ptr(), write->size()), + [this, writeq{std::move(writeq)}](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_write(std::move(writeq), ec, bytes_transferred); }); + */ + boost::asio::async_write( + *_socket, boost::asio::buffer(write->ptr(), write->size()), + [this, writeq](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_write(writeq, ec, bytes_transferred); }); +} + +void DataStream::handle_write( + writeq_type *writeq, + const boost::system::error_code& ec, + size_t bytes_transferred) { + // current write is first element in writeq, so writeq must be non-empty + assert(writeq /* ouch! */ && !writeq->empty()); + writeq->front()->onFinish(ec, bytes_transferred); + writeq->pop(); + + if (ec) { + // TODO Handle errors + } + + start_write(writeq); // process remaining writes +} + +} // namespace comm + +} // namespace dclasio diff --git a/dclasio/src/dclasio/comm/DataStream.h b/dclasio/src/dclasio/comm/DataStream.h new file mode 100644 index 0000000..e4a27ad --- /dev/null +++ b/dclasio/src/dclasio/comm/DataStream.h @@ -0,0 +1,179 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DataStream.h + * + * \date 2014-03-07 + * \author Philipp Kegel + */ + +#ifndef DATASTREAM_H_ +#define DATASTREAM_H_ + +#include "DataTransferImpl.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +// TODO Split DataStream into InputDataStream and OutputDataStream to model simplex connections and reduce code redundancy +/*! + * \brief A data stream maintains a set of incoming and outgoing data transfers from/to a single remote process + */ +class DataStream { +public: + typedef std::queue, std::list>> readq_type; + typedef std::queue, std::list>> writeq_type; + + // TODO Accept rvalue reference rather than pointer to socket (requires Boost 1.47) + /*! + * \brief Creates a data stream from a connected socket + * The data stream becomes owner of the socket. + * + * \param[in] socket the socket to use for the data stream + */ + DataStream( + const std::shared_ptr& socket); + /*! + * \brief Creates a data stream to the specified remote endpoint + * + * \param socket a socket associated with a local endpoint + * \param remote_endpoint the remote process + */ + DataStream( + const std::shared_ptr& socket, + boost::asio::ip::tcp::endpoint remote_endpoint); + virtual ~DataStream(); + + /*! + * \brief Connects this data stream to its remote process + * The ID of the local process associated with this data stream is send to + * the remote process. + * + * \param[in] pid ID of the local process + * \return the ID of the remote process, or 0 if the connection has been rejected + */ + dcl::process_id connect( + dcl::process_id pid); + + void disconnect(); + + /*! + * \brief Submits a data receipt for this data stream + * + * \param[in] size number of bytes to receipt + * \param[in] ptr destination buffer for received bytes + * \return a handle for the data receipt + */ + std::shared_ptr read( + size_t size, + void *ptr); + + /*! + * \brief Submits a data sending for this data stream + * + * \param[in] size number of bytes to send + * \param[in] ptr source buffer for sent bytes + * \return a handle for the data sending + */ + std::shared_ptr write( + size_t size, + const void *ptr); + +private: + /* Data streams must be non-copyable */ + DataStream( + const DataStream&) = delete; + DataStream& operator=( + const DataStream&) = delete; + + /*! + * \brief Processes the next data transfer from the read queue. + * + * \param[in] readq list of incoming data transfers to process + * If \c readq is empty, it is filled with data transfers from the stream's internal read queue + */ + void start_read( + readq_type *readq = new readq_type()); + + void handle_read( + readq_type *readq, + const boost::system::error_code& ec, + size_t bytes_transferred); + + /*! + * \brief Processes the next data transfer from the write queue. + * + * \param[in] writeq list of incoming data transfers to process + * If \c writeq is empty, it is filled with data transfers from the stream's internal write queue + */ + void start_write( + writeq_type *writeq = new writeq_type()); + + void handle_write( + writeq_type *writeq, + const boost::system::error_code& ec, + size_t bytes_transferred); + + // TODO Store socket instance rather than smart pointer + std::shared_ptr _socket; //!< I/O object for remote process + boost::asio::ip::tcp::endpoint _remote_endpoint; //!< remote endpoint of data stream + + bool _receiving; //!< \c true, if currently receiving data, otherwise \c false + bool _sending; //!< \c true, if currently sending data, otherwise \c false + readq_type _readq; //!< pending data receipts + std::mutex _readq_mtx; //!< protects read queue and flag + writeq_type _writeq; //!< pending data sendings + std::mutex _writeq_mtx; //!< protects write queue and flag +}; + +} // namespace comm + +} // namespace dclasio + +#endif /* DATASTREAM_H_ */ diff --git a/dclasio/src/dclasio/comm/DataTransferImpl.h b/dclasio/src/dclasio/comm/DataTransferImpl.h new file mode 100644 index 0000000..1113a94 --- /dev/null +++ b/dclasio/src/dclasio/comm/DataTransferImpl.h @@ -0,0 +1,247 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DataTransferImpl.h + * + * \date 2011-12-17 + * \author Philipp Kegel + */ + +#ifndef DATATRANSFERIMPL_H_ +#define DATATRANSFERIMPL_H_ + +#include +#include + +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +struct Receive { + typedef void * pointer_type; + + static void logFinish( + size_t size, + double latency, + double bandwidth) { + dcl::util::Logger << dcl::util::Debug + << "Received " << size << " bytes\n" + << "\tlatency: " << latency << " ms, bandwidth: " << bandwidth << " MB/s" + << std::endl; + + } +}; + +struct Send { + typedef const void * pointer_type; + + static void logFinish( + size_t size, + double latency, + double bandwidth) { + dcl::util::Logger << dcl::util::Debug + << "Sent " << size << " bytes\n" + << "\tlatency: " << latency << " ms, bandwidth: " << bandwidth << " MB/s" + << std::endl; + } +}; + +/* ****************************************************************************/ + +template +class DataTransferImpl: public dcl::DataTransfer { +private: + /*! + * \brief Executes all of this data transfer's callbacks. + */ + void triggerCallbacks() { + std::lock_guard lock(_mutex); + // TODO Do not lock data transfer while executing callbacks + for (auto& callback : _callbacks) { + callback(_status); + } + } + +public: + DataTransferImpl( + size_t size, typename Operation::pointer_type ptr) : + _size(size), _ptr(ptr), + _submit(dcl::util::clock.getTime()), _start(0L), _end(0L), + _status(CL_SUBMITTED) { } + + void setCallback( + const std::function& notify) { + std::lock_guard lock(_mutex); + + if (_status == CL_SUCCESS || _status < 0) { // data transfer is already finished + /* The data transfer is already finished, but it is undefined whether + * the callback list has already been processed or not. + * Hence, if a new callback is added to the callback list it might + * eventually be called or not. + * Adding the new callback to the callback list and calling it might + * result in a redundant execution of the callback. + * Therefore, call the new callback immediately without adding it to the + * callback list to ensure that it is only called once. */ + notify(_status); + } else { + /* Since we obtained the lock for the callback list while the data + * transfer was still in progress we can be sure that the data + * transfer will not be finished by onFinish, before we added the new + * callback. */ + _callbacks.push_back(notify); + } + } + + cl_ulong submit() const { + // TODO Throw error if DataTransfer is not submitted yet + return _submit; + } + + cl_ulong start() const { + // TODO Throw error if DataTransfer is not started yet + return _start; + } + + cl_ulong end() const { + // TODO Throw error if DataTransfer is not finished yet + return _end; + } + + bool isComplete() const { + std::lock_guard lock(_mutex); + return (_status == CL_SUCCESS || _status < 0); + } + + void wait() const { + std::lock_guard lock(_mutex); + while (_status != CL_SUCCESS && _status > 0) { + _statusChanged.wait(_mutex); + } + if (_status < 0) { + throw dcl::IOException("Data transfer failed"); + } + } + + void abort() { + std::lock_guard lock(_mutex); + /* TODO Implement DataTransferImpl::abort */ + } + + size_t size() const { + return _size; + } + + typename Operation::pointer_type ptr() const { + return _ptr; + } + + void onStart() { + std::lock_guard lock(_mutex); + _start = dcl::util::clock.getTime(); // take time stamp + _status = CL_RUNNING; + // signal start + _statusChanged.notify_all(); + } + + void onFinish( + const boost::system::error_code& ec, + size_t bytes_transferred) { + std::unique_lock lock(_mutex); + _end = dcl::util::clock.getTime(); // take time stamp + + double latency = static_cast(_start - _submit) / 1000000.0; + double durance = static_cast(_end - _start) / 1000000000.0; + + // TODO Use more specific error codes + _status = ec ? CL_IO_ERROR_WWU : CL_SUCCESS; + // signal completion + _statusChanged.notify_all(); + lock.unlock(); + + triggerCallbacks(); + + double bandwidth = (_size / static_cast(1024 * 1024)) / durance; + Operation::logFinish(_size, latency, bandwidth); + } + +private: + const size_t _size; + typename Operation::pointer_type _ptr; + + cl_ulong _submit; + cl_ulong _start; + cl_ulong _end; + + cl_int _status; //!< status of data transfer + std::vector> _callbacks; + + mutable std::mutex _mutex; + mutable std::condition_variable_any _statusChanged; +}; + +/* ****************************************************************************/ + +typedef DataTransferImpl DataReceipt; +typedef DataTransferImpl DataSending; + +} /* namespace comm */ + +} /* namespace dclasio */ + +#endif /* DATATRANSFERIMPL_H_ */ diff --git a/dclasio/src/dclasio/comm/MessageDispatcher.cpp b/dclasio/src/dclasio/comm/MessageDispatcher.cpp new file mode 100644 index 0000000..36baeb9 --- /dev/null +++ b/dclasio/src/dclasio/comm/MessageDispatcher.cpp @@ -0,0 +1,278 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MessageDispatcher.cpp + * + * \date 2014-03-10 + * \author Philipp Kegel + */ + +#include "MessageDispatcher.h" + +#include "../DCLAsioTypes.h" +#include "../ProcessImpl.h" + +#include "ConnectionListener.h" +#include "MessageListener.h" +#include "MessageQueue.h" + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +namespace dclasio { +namespace comm { + +MessageDispatcher::MessageDispatcher( + dcl::process_id pid) : _work(_io_service), _pid(pid) { +} + +MessageDispatcher::~MessageDispatcher() { + stop(); +} + +message_queue * MessageDispatcher::create_message_queue( + const endpoint_type& endpoint) { + // create socket + auto socket(std::make_shared(_io_service)); + return add_message_queue(new message_queue(socket, endpoint)); +} + +void MessageDispatcher::destroy_message_queue(message_queue *msgq) { + std::lock_guard lock(_mutex); + // remove message queue from list; implicitly calls destructor + _message_queues.remove_if([msgq](const std::unique_ptr& entry){ + return entry.get() == msgq; }); +} + +void MessageDispatcher::add_connection_listener( + connection_listener& listener) { + std::lock_guard lock(_listener_mutex); + _connection_listeners.insert(&listener); +} + +void MessageDispatcher::remove_connection_listener( + connection_listener& listener) { + std::lock_guard lock(_listener_mutex); + _connection_listeners.erase(& listener); +} + +void MessageDispatcher::add_message_listener( + message_listener& listener) { + std::lock_guard lock(_listener_mutex); + _message_listeners.insert(&listener); +} + +void MessageDispatcher::remove_message_listener( + message_listener& listener) { + std::lock_guard lock(_listener_mutex); + _message_listeners.erase(&listener); +} + +void MessageDispatcher::bind(const endpoint_type& endpoint) { + // create server socket + _acceptor.reset(new boost::asio::ip::tcp::acceptor(_io_service)); + _acceptor->open(boost::asio::ip::tcp::v4()); + _acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + _acceptor->bind(endpoint); +} + +void MessageDispatcher::start() { + if (_acceptor) { + try { + _acceptor->listen(); + + // start accept loop + start_accept(); + } catch (const boost::system::system_error& err) { + dcl::util::Logger << dcl::util::Error + << "Could not start message queue acceptor: " << err.what() + << std::endl; + } + } + + /* start worker thread + * use lambda to resolve overloaded boost::asio::io_service::run */ + _worker = std::thread([this](){ _io_service.run(); }); +} + +void MessageDispatcher::stop() { + _io_service.stop(); + if (_worker.joinable()) _worker.join(); +} + +void MessageDispatcher::start_accept() { + auto socket(std::make_shared(_io_service)); + // await incoming message queue connection + _acceptor->async_accept(*socket, + [this, socket](const boost::system::error_code& ec){ + handle_accept(socket, ec); }); +} + +void MessageDispatcher::handle_accept( + std::shared_ptr socket, + const boost::system::error_code& ec) { + // TODO Handle error + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not accept message queue: " << ec.message() + << std::endl; + return; + } + + auto buf(std::make_shared()); + buf->resize(sizeof(dcl::process_id) + 2); + + // await authentication request from incoming data stream + boost::asio::async_read( + *socket, + boost::asio::buffer(buf->begin(), buf->size()), + [this, socket, buf](const boost::system::error_code& ec, size_t bytes_transferred) { + handle_approval(socket, buf, ec, bytes_transferred); }); + + start_accept(); // await another incoming message queue connection +} + +void MessageDispatcher::handle_approval( + std::shared_ptr socket, + std::shared_ptr buf, + const boost::system::error_code& ec, + size_t bytes_transferred) { + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not approve data stream: " << ec.message() + << std::endl; + return; + } + + dcl::process_id pid; + uint8_t proc_type; // process type + uint8_t proto; // protocol (must be message queue) + *buf >> pid >> proc_type >> proto; + // TODO Ensure pid != 0 + ProcessImpl::Type process_type = static_cast(proc_type); + // TODO Ensure message queue protocol + + // request connection approval + std::unique_lock lock(_listener_mutex); + std::vector listeners( + std::begin(_connection_listeners), std::end(_connection_listeners)); + lock.unlock(); + bool approved = false; + for (auto listener : listeners) { + if (listener->approve_message_queue(process_type, pid)) { + approved = true; + break; + } + } + + if (approved) { + // message queue has been approved - keep it + auto msgq = add_message_queue(new message_queue(socket, pid)); + + *buf << _pid; // signal approval: return own process ID + boost::asio::write(*socket, boost::asio::buffer(buf->begin(), buf->size())); + dcl::util::Logger << dcl::util::Verbose + << "Accepted message queue from process (pid=" << pid << ')' + << std::endl; + + for (auto listener : listeners) { + listener->message_queue_connected(*msgq, process_type, pid); + } + + // start reading messages from queue + start_read_message(*msgq); + } else { + // signal reject: return process ID 0 + *buf << dcl::process_id(0); + boost::asio::write(*socket, boost::asio::buffer(buf->begin(), buf->size())); + dcl::util::Logger << dcl::util::Error + << "Rejected message queue from process (pid=" << pid << ')' + << std::endl; + } +} + +void MessageDispatcher::start_read_message( + message_queue& msgq) { + msgq.recv_message( + [this, &msgq] (message::Message *message, const boost::system::error_code& ec) { + handle_message(msgq, message, ec); }); +} + +/*! + * \brief Callback for incoming messages + */ +void MessageDispatcher::handle_message( + message_queue& msgq, + message::Message *message, + const boost::system::error_code& ec) { + if (ec) { + // TODO Handle errors + std::lock_guard lock(_listener_mutex); + for (auto listener : _connection_listeners) { + listener->message_queue_disconnected(msgq); + } + } else { + assert(message && "No message"); + std::unique_lock lock(_listener_mutex); + for (auto listener : _message_listeners) { + listener->message_received(msgq, *message); + } + lock.unlock(); + + // read next message + start_read_message(msgq); + } +} + +} /* namespace comm */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/comm/MessageDispatcher.h b/dclasio/src/dclasio/comm/MessageDispatcher.h new file mode 100644 index 0000000..1c9af0e --- /dev/null +++ b/dclasio/src/dclasio/comm/MessageDispatcher.h @@ -0,0 +1,177 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MessageDispatcher.h + * + * \date 2014-03-10 + * \author Philipp Kegel + */ + +#ifndef MESSAGEDISPATCHER_H_ +#define MESSAGEDISPATCHER_H_ + +#include "../DCLAsioTypes.h" +#include "../ProcessImpl.h" + +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace dclasio { +namespace comm { + +class connection_listener; +class message_listener; +class message_queue; + +/* ****************************************************************************/ + +/*! + * \brief Processes incoming message queue connections and message transfers. + */ +class MessageDispatcher { +public: + MessageDispatcher( + dcl::process_id pid); + virtual ~MessageDispatcher(); + + /*! + * \brief Creates a message queue associated to the specified remote process + * + * \param endpoint endpoint of the remote process + */ + message_queue * create_message_queue( + const endpoint_type& endpoint); + void destroy_message_queue( + message_queue *msgq); + + void add_connection_listener( + connection_listener& listener); + void remove_connection_listener( + connection_listener& listener); + + void add_message_listener( + message_listener& listener); + void remove_message_listener( + message_listener& listener); + + void bind( + const endpoint_type& endpoint); + + void start(); + void stop(); + + // FIXME MessageDispatcher::start_read_message should be private + void start_read_message( + message_queue& msgq); + +private: + void start_accept(); + + void handle_accept( + std::shared_ptr socket, + const boost::system::error_code& ec); + + /*! + * \brief Callback for message queue handshake + * This method authenticates an incoming message queue and either notifies + * registered connection listeners, or rejects and closes the message queue. + * + * \param[in] socket socket of incoming message queue + * \param[in] buf identification received from message queue + * \param[in] ec error code + * \param[in] bytes_transferred number of received bytes + */ + void handle_approval( + std::shared_ptr socket, + std::shared_ptr buf, + const boost::system::error_code& ec, + size_t bytes_transferred); + + /*! + * \brief Callback for incoming messages + */ + void handle_message( + message_queue& msgq, + message::Message *message, + const boost::system::error_code& ec); + + /*! + * \brief Adds a message queue to this message dispatcher + * + * \param[in] args arguments for emplacing a unique pointer to the message queue + * \return a raw pointer to the added message queue + */ + template + message_queue * add_message_queue( + Args&& ... args) { + std::lock_guard lock(_mutex); + _message_queues.emplace_back(std::forward(args) ...); + return _message_queues.back().get(); + } + + boost::asio::io_service _io_service; + boost::asio::io_service::work _work; //!< work flag for I/O service + std::unique_ptr _acceptor; //!< server socket + + dcl::process_id _pid; + std::thread _worker; + + std::list> _message_queues; //!< message queues managed by this message dispatcher + std::unordered_set _connection_listeners; //!< connection listeners + std::unordered_set _message_listeners; //!< message listeners + std::mutex _mutex; //!< protects message queue container + std::mutex _listener_mutex; //!< protects connection and message listener containers + +}; + +} /* namespace comm */ +} /* namespace dclasio */ + +#endif /* MESSAGEDISPATCHER_H_ */ diff --git a/dclasio/src/dclasio/comm/MessageListener.h b/dclasio/src/dclasio/comm/MessageListener.h new file mode 100644 index 0000000..aab377c --- /dev/null +++ b/dclasio/src/dclasio/comm/MessageListener.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MessageListener.h + * + * \date 2014-03-10 + * \author Philipp Kegel + */ + +#ifndef MESSAGELISTENER_H_ +#define MESSAGELISTENER_H_ + +#include + +namespace dclasio { + +namespace message { + +class Message; + +} /* namespace message */ + +namespace comm { + +class message_queue; + +/* ****************************************************************************/ + +class message_listener { +public: + virtual ~message_listener() { }; + virtual void message_received( + message_queue& msgq, + const message::Message& message) = 0; +}; + +} /* namespace comm */ +} /* namespace dclasio */ + +#endif /* MESSAGELISTENER_H_ */ diff --git a/dclasio/src/dclasio/comm/MessageQueue.cpp b/dclasio/src/dclasio/comm/MessageQueue.cpp new file mode 100644 index 0000000..15735b4 --- /dev/null +++ b/dclasio/src/dclasio/comm/MessageQueue.cpp @@ -0,0 +1,234 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MessageQueue.cpp + * + * \date 2014-03-10 + * \author Philipp Kegel + */ + +#include "MessageQueue.h" + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +// TODO Replace htonl, ntohl by own, portable implementation +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { +namespace comm { + +message_queue::message_queue( + const std::shared_ptr& socket, dcl::process_id pid) : + _socket(socket), _pid(pid) { + // TODO Ensure that socket is connected + _remote_endpoint = _socket->remote_endpoint(); + /* Disable Nagle's algorithm on listening socket + * Due to the RPC-style protocol of dOpenCL, short messages usually wait for + * a response before the next message is send. Hence, waiting for another + * short message to merge with the first one is pointless. + * In particular, command status messages suffer from the high latency + * introduced by Nagle's algorithm. */ + _socket->set_option(boost::asio::ip::tcp::no_delay(true)); +} + +message_queue::message_queue( + const std::shared_ptr& socket, + boost::asio::ip::tcp::endpoint remote_endpoint) : + _socket(socket), _remote_endpoint(remote_endpoint), _pid(0) { + assert(!socket->is_open()); // socket must not be connect +} + +message_queue::message_queue( + message_queue&& other) : _socket(std::move(other._socket)), + _remote_endpoint(other._remote_endpoint), _pid(other._pid) { +} + +message_queue::~message_queue() { +} + +dcl::process_id message_queue::connect( + ProcessImpl::Type process_type, + dcl::process_id pid) { + _socket->connect(_remote_endpoint); // connect socket + /* Disable Nagle's algorithm on listening socket + * Due to the RPC-style protocol of dOpenCL, short messages usually wait for + * a response before the next message is send. Hence, waiting for another + * short message to merge with the first one is pointless. + * In particular, command status messages suffer from the high latency + * introduced by Nagle's algorithm. */ + _socket->set_option(boost::asio::ip::tcp::no_delay(true)); + + // send local process ID and type to remote process + // TODO Encode message queue protocol + dcl::ByteBuffer buf; + buf << pid << uint8_t(process_type) << uint8_t(0); + boost::asio::write(*_socket, boost::asio::buffer(buf.begin(), buf.size())); + dcl::util::Logger << dcl::util::Verbose + << "Sent process identification message for message queue (process type=" + << (process_type == ProcessImpl::Type::HOST ? "HOST" : "COMPUTE_NODE") + << ", pid=" << pid << ')' + << std::endl; + + // receive response + buf.resize(sizeof(dcl::process_id)); + boost::asio::read(*_socket, boost::asio::buffer(buf.begin(), buf.size())); + buf >> _pid; + dcl::util::Logger << dcl::util::Verbose + << "Received identification message response (pid=" << _pid << ')' + << std::endl; + + return _pid; +} + +void message_queue::disconnect() { + _socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); + _socket->close(); +} + +void message_queue::send_message( + const message::Message& message) { +#if defined(USE_SEND_BUFFER) + std::lock_guard lock(_mutex); + + _send_buffer.resize(0); + message.pack(_send_buffer); + _send_header.size = htonl(_send_buffer.size()); + _send_header.type = htonl(message.get_type()); + // send message header and body in one go + boost::asio::write(*_socket, std::vector( { + boost::asio::const_buffer(&_send_header, sizeof(header_type)), + boost::asio::const_buffer(_send_buffer.begin(), _send_buffer.size()) })); + + dcl::util::Logger << dcl::util::Verbose + << "Sent message (size=" << _send_buffer.size() << ", type=" << message.get_type() << ')' + << std::endl; +#else + // send message length and type (4 + 4 Byte), followed by message body + dcl::ByteBuffer buf; + message.pack(buf); // pack message to determine length + header_type header({ htonl(buf.size()), htonl(message.get_type()) }); + + std::lock_guard lock(_mutex); + // send message header and body in one go + boost::asio::write(*_socket, std::vector( { + boost::asio::const_buffer(&header, sizeof(header_type)), + boost::asio::const_buffer(buf.begin(), buf.size()) })); + + dcl::util::Logger << dcl::util::Verbose + << "Sent message (size=" << buf.size() << ", type=" << message.get_type() << ')' + << std::endl; +#endif +} + +void message_queue::start_read_header() { + // read header + boost::asio::async_read(*_socket, + boost::asio::buffer(&_message_header, sizeof(header_type)), + [this](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_header(ec, bytes_transferred); }); +} + +void message_queue::handle_header( + const boost::system::error_code& ec, + size_t bytes_transferred) { + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not read message header: " << ec.message() + << std::endl; + // FIXME Report error via MessageHandler + } else { + // extract message size and type from header and start reading message body + start_read_message(ntohl(_message_header.size)); + } +} + +void message_queue::start_read_message( + message::Message::size_type size) { + dcl::util::Logger << dcl::util::Verbose + << "Incoming message (size=" << size << ')' << std::endl; + _message_buffer.resize(size); + // read message + boost::asio::async_read(*_socket, + boost::asio::buffer(_message_buffer.begin(), _message_buffer.size()), + [this](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_message(ec, bytes_transferred); }); +} + +void message_queue::handle_message( + const boost::system::error_code& ec, + size_t bytes_transferred) { + std::unique_ptr message; + + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not read message: " << ec.message() + << std::endl; + } else { + // create message of type _message_header.type from _message_buffer + message.reset(message::createMessage(ntohl(_message_header.type))); + dcl::util::Logger << dcl::util::Debug + << "Received message (size=" << _message_buffer.size() + << ", type=" << message->get_type() << ')' + << std::endl; + + message->unpack(_message_buffer); // restore message from buffer + } + + // FIXME Return message or report error via MessageHandler +} + +} /* namespace comm */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/comm/MessageQueue.h b/dclasio/src/dclasio/comm/MessageQueue.h new file mode 100644 index 0000000..e67807b --- /dev/null +++ b/dclasio/src/dclasio/comm/MessageQueue.h @@ -0,0 +1,236 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MessageQueue.h + * + * \date 2014-03-10 + * \author Philipp Kegel + */ + +#ifndef MESSAGEQUEUE_H_ +#define MESSAGEQUEUE_H_ + +#include "../ProcessImpl.h" + +#include + +#include +#include + +#if !defined(NO_TEMPLATES) +#include + +#include +#endif + +#include + +#include + +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace message { + +class Message; + +} /* namespace message */ + +/* ****************************************************************************/ + +namespace comm { + +class message_queue { +public: + /*! + * \brief Creates a message queue from a connected socket + * \param[in] socket the socket + */ + message_queue( + const std::shared_ptr& socket, + dcl::process_id pid); + /*! + * \brief Creates a message queue to the specified remote endpoint + * + * \param socket a socket associated with a local endpoint + * \param remote_endpoint the remote process + */ + message_queue( + const std::shared_ptr& socket, + boost::asio::ip::tcp::endpoint remote_endpoint); + message_queue( + message_queue&& other); + virtual ~message_queue(); + + dcl::process_id get_process_id() const { return _pid; } + + /*! + * \brief Connects this message queue to a remote process + * Moreover, the ID of the local process associated with this message queue is + * send to the remote process. + * + * \param process_type type of the local process + * \param process_id ID of the local process + * \return the ID of the remote process, or 0 if the connection has been rejected + */ + dcl::process_id connect( + dclasio::ProcessImpl::Type process_type, + dcl::process_id process_id); + + void disconnect(); + + void send_message( + const message::Message& message); + + template + void recv_message( + // TODO Provide message location as input +// message::Message *& message, + MessageHandler handler) { + start_read_header(handler); + } + +private: + typedef struct { + message::Message::size_type size; + message::Message::class_type type; + } header_type; //!< message header comprising size of message body and message type ID + + void start_read_header(); + void handle_header( + const boost::system::error_code& ec, + size_t bytes_transferred); + void start_read_message( + message::Message::size_type size); + void handle_message( + const boost::system::error_code& ec, + size_t bytes_transferred); + + template + void start_read_header( + MessageHandler handler) { + // read header + boost::asio::async_read(*_socket, + boost::asio::buffer(&_message_header, sizeof(header_type)), + [this, handler](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_header(ec, bytes_transferred, handler); }); + } + + template + void handle_header( + const boost::system::error_code& ec, + size_t bytes_transferred, + MessageHandler handler) { + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not read message header: " << ec.message() + << std::endl; + // FIXME Report error asynchronously + handler(nullptr, ec); + } else { + // extract message size and type from header and start reading message body + start_read_message(ntohl(_message_header.size), handler); + } + } + + template + void start_read_message( + message::Message::size_type size, + MessageHandler handler) { + dcl::util::Logger << dcl::util::Verbose + << "Incoming message (size=" << size << ')' << std::endl; + _message_buffer.resize(size); + // read message + boost::asio::async_read(*_socket, + boost::asio::buffer(_message_buffer.begin(), _message_buffer.size()), + [this, handler](const boost::system::error_code& ec, size_t bytes_transferred){ + handle_message(ec, bytes_transferred, handler); }); + } + + template + void handle_message( + const boost::system::error_code& ec, + size_t bytes_transferred, + MessageHandler handler) { + std::unique_ptr message; + + if (ec) { + dcl::util::Logger << dcl::util::Error + << "Could not read message: " << ec.message() + << std::endl; + } else { + // create message of type _message_header.type from _message_buffer + message.reset(message::createMessage(ntohl(_message_header.type))); + dcl::util::Logger << dcl::util::Debug + << "Received message (size=" << _message_buffer.size() + << ", type=" << message->get_type() << ')' + << std::endl; + + message->unpack(_message_buffer); // restore message from buffer + } + + /* FIXME Return message and report error asynchronously + _socket->get_io_service().post([handler, message, ec] () { handler(message, ec); }); + */ + handler(message.get(), ec); + } + + // TODO Store socket instance rather than smart pointer to instance + std::shared_ptr _socket; //!< I/O object for remote process + boost::asio::ip::tcp::endpoint _remote_endpoint; //!< remote endpoint of message queue + header_type _message_header; + dcl::ByteBuffer _message_buffer; +#if defined(USE_SEND_BUFFER) + header_type _send_header; + dcl::ByteBuffer _send_buffer; +#endif + /* FIXME Remove process ID from message_queue + * This is a hack to avoid a message_queue-to-process_id lookup table in MessageDispatcher */ + dcl::process_id _pid; + + std::recursive_mutex _mutex; //! mutex to protect output channel +}; + +} /* namespace comm */ +} /* namespace dclasio */ + +#endif /* MESSAGEQUEUE_H_ */ diff --git a/dclasio/src/dclasio/comm/ResponseBuffer.cpp b/dclasio/src/dclasio/comm/ResponseBuffer.cpp new file mode 100644 index 0000000..95e7b87 --- /dev/null +++ b/dclasio/src/dclasio/comm/ResponseBuffer.cpp @@ -0,0 +1,162 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file ResponseBuffer.cpp + * + * @date 2011-04-18 + * @author Philipp Kegel + */ + +#include "ResponseBuffer.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +ResponseBuffer::ResponseBuffer(size_t size) : + _interrupt(false) { + _responses.resize(size); + _tail = _head = std::begin(_responses); +} + +ResponseBuffer::~ResponseBuffer() { +} + +void ResponseBuffer::put(std::unique_ptr&& response) { + std::lock_guard lock(_mutex); + + while (!_interrupt && !insert(std::move(response))) { + _responseRemoved.wait(_mutex); + } + if (_interrupt) throw dcl::ThreadInterrupted(); +} + +std::unique_ptr ResponseBuffer::tryGet(const message::Request& request) { + std::lock_guard lock(_mutex); + return remove(request); +} + +std::unique_ptr ResponseBuffer::get(const message::Request& request) { + std::lock_guard lock(_mutex); + std::unique_ptr response; + + while (!_interrupt && !(response = remove(request))) { + _responseAdded.wait(_mutex); + }; + if (_interrupt) throw dcl::ThreadInterrupted(); + + return response; +} + +void ResponseBuffer::interrupt() { + std::lock_guard lock(_mutex); + _interrupt = true; + _responseAdded.notify_all(); + _responseRemoved.notify_all(); +} + +void ResponseBuffer::clear() { + std::lock_guard lock(_mutex); + + _responses.clear(); + _tail = _head = std::begin(_responses); + + _responseRemoved.notify_all(); +} + +bool ResponseBuffer::insert(std::unique_ptr&& response) { + std::vector>::iterator i = _tail; + + do { + std::vector>::iterator entry = i; + + /* next buffer position */ + if (++i == std::end(_responses)) { + i = std::begin(_responses); + } + + if (!*entry) { + *entry = std::move(response); /* move response into buffer */ + _tail = i; /* remember next buffer position for subsequent insert operation */ + _responseAdded.notify_all(); + break; + } + } while (i != _tail); /* only run through buffer once */ + + return (response == nullptr); +} + +std::unique_ptr ResponseBuffer::remove(const message::Request& request) { + std::unique_ptr response; + std::vector>::iterator i = _head; + + do { + std::vector>::iterator entry = i; + + /* next buffer position */ + if (++i == std::end(_responses)) { + i = std::begin(_responses); + } + if (*entry && (*entry)->get_request_id() == request.id) { + response = std::move(*entry); /* remove response from buffer + (must be removed *before* notification) */ + _head = i; /* remember next buffer position for subsequent search */ + _responseRemoved.notify_one(); + break; + } + + } while (i != _head); /* only run through buffer once */ + + return response; +} + +} /* namespace comm */ + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/comm/ResponseBuffer.h b/dclasio/src/dclasio/comm/ResponseBuffer.h new file mode 100644 index 0000000..704a57b --- /dev/null +++ b/dclasio/src/dclasio/comm/ResponseBuffer.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file ResponseBuffer.h + * + * @date 2011-04-18 + * @author Philipp Kegel + */ + +#ifndef RESPONSEBUFFER_H_ +#define RESPONSEBUFFER_H_ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace dclasio { + +namespace comm { + +/** + * @class A ring buffer for saving responses from compute nodes. + */ +class ResponseBuffer { +public: + static const size_t DEFAULT_SIZE = 64; + + ResponseBuffer( + size_t size = DEFAULT_SIZE); + virtual ~ResponseBuffer(); + + void put( + std::unique_ptr&& response); + /* TODO Add timed method for adding responses */ + + std::unique_ptr tryGet( + const message::Request& request); + /** + * @brief Waits for a response indefinitely. + * + * @param[in] request the request which is associated with the response + * @return the response + */ + std::unique_ptr get( + const message::Request& request); + + /** + * @brief Waits for a response. + * + * @param[in] request the request which is associated with the response + * @param[in] timeout a timeout + * @return the response, or NULL if @c timeout has been reached + */ + template + std::unique_ptr get( + const message::Request& request, + const std::chrono::duration& timeout) { + std::lock_guard lock(_mutex); + std::unique_ptr response; + + while (!_interrupt && !(response = remove(request))) { + if (_responseAdded.wait_for(_mutex, timeout) == std::cv_status::timeout) { + /* timeout expired */ + break; + } + }; + if (_interrupt) throw dcl::ThreadInterrupted(); + + return response; + } + + void interrupt(); + void clear(); + +private: + bool insert( + std::unique_ptr&& response); + std::unique_ptr remove( + const message::Request& request); + + std::vector> _responses; + std::vector>::iterator _head, _tail; + + std::mutex _mutex; /**< buffer mutex */ + std::condition_variable_any _responseAdded; /**< condition: added response to buffer */ + std::condition_variable_any _responseRemoved; /**< condition: removed response from buffer */ + bool _interrupt; +}; + +} /* namespace comm */ + +} /* namespace dclasio */ + +#endif /* RESPONSEBUFFER_H_ */ diff --git a/dclasio/src/dclasio/message/BuildProgram.cpp b/dclasio/src/dclasio/message/BuildProgram.cpp new file mode 100644 index 0000000..f21e5a4 --- /dev/null +++ b/dclasio/src/dclasio/message/BuildProgram.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file BuildProgram.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include + +#include +#include + +#include +#include + +namespace dclasio { +namespace message { + +BuildProgram::BuildProgram() : + _programId(0) { +} + +BuildProgram::BuildProgram( + dcl::object_id programId, + const std::vector& deviceIds, + const std::string& options, + dcl::object_id programBuildId) : + _programId(programId), _deviceIds(deviceIds), _options(options), + _programBuildId(programBuildId) +{ +} + +BuildProgram::BuildProgram(const BuildProgram& rhs) : + Request(rhs), _programId(rhs._programId), _deviceIds( + rhs._deviceIds), _options(rhs._options) { +} + +dcl::object_id BuildProgram::programId() const { + return _programId; +} + +const std::vector& BuildProgram::deviceIds() const { + return _deviceIds; +} + +const std::string& BuildProgram::options() const { + return _options; +} + +dcl::object_id BuildProgram::programBuildId() const { + return _programBuildId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CommandMessage.cpp b/dclasio/src/dclasio/message/CommandMessage.cpp new file mode 100644 index 0000000..f379a0e --- /dev/null +++ b/dclasio/src/dclasio/message/CommandMessage.cpp @@ -0,0 +1,87 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CommandMessage.cpp + * + * Command related messages + * + * \date 2011-07-11 + * \author Philipp Kegel + */ + +#include + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +namespace message { + +CommandExecutionStatusChangedMessage::CommandExecutionStatusChangedMessage() : + _commandId(0), _status(CL_SUBMITTED) { +} + +CommandExecutionStatusChangedMessage::CommandExecutionStatusChangedMessage( + dcl::object_id commandId, cl_int status): + _commandId(commandId), _status(status) { +} + +CommandExecutionStatusChangedMessage::CommandExecutionStatusChangedMessage( + const CommandExecutionStatusChangedMessage& rhs) : + _commandId(rhs._commandId), _status(rhs._status) { +} + +CommandExecutionStatusChangedMessage::~CommandExecutionStatusChangedMessage() { } + +dcl::object_id CommandExecutionStatusChangedMessage::commandId() const { + return _commandId; +} + +cl_int CommandExecutionStatusChangedMessage::status() const { + return _status; +} + +} /* namespace message */ + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/ContextErrorMessage.h b/dclasio/src/dclasio/message/ContextErrorMessage.h new file mode 100644 index 0000000..7efb512 --- /dev/null +++ b/dclasio/src/dclasio/message/ContextErrorMessage.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ContextErrorMessage.h + * + * \date 2014-04-12 + * \author Sebastian Pribnow + */ + +#ifndef CONTEXTERRORMESSAGE_H_ +#define CONTEXTERRORMESSAGE_H_ + +#include + +#include +#include +#include + +#include + +namespace dclasio { + +namespace message { + +/*! + * \brief Notification of context error. + * + * This message is sent from compute nodes to the host. + */ +class ContextErrorMessage: public Message { +public: + ContextErrorMessage() { + } + ContextErrorMessage( + dcl::object_id contextId_, + const std::string& errInfo_, + const dcl::Binary& privateInfo_) : + contextId(contextId_), errorInfo(errInfo_), privateInfo( + privateInfo_) { + } + ContextErrorMessage(const ContextErrorMessage& rhs) : + contextId(rhs.contextId), errorInfo(rhs.errorInfo), privateInfo( + rhs.privateInfo) { + } + virtual ~ContextErrorMessage() { + } + + dcl::object_id contextId; + std::string errorInfo; + dcl::Binary privateInfo; + + static const class_type TYPE = 8599; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + buf << contextId << errorInfo << privateInfo; + } + + void unpack(dcl::ByteBuffer& buf) { + buf >> contextId >> errorInfo >> privateInfo; + } +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* CONTEXTERRORMESSAGE_H_ */ diff --git a/dclasio/src/dclasio/message/CreateBuffer.cpp b/dclasio/src/dclasio/message/CreateBuffer.cpp new file mode 100644 index 0000000..ce44f23 --- /dev/null +++ b/dclasio/src/dclasio/message/CreateBuffer.cpp @@ -0,0 +1,93 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { +namespace message { + +CreateBuffer::CreateBuffer() { +} + +CreateBuffer::CreateBuffer( + dcl::object_id bufferId, + dcl::object_id contextId, + cl_mem_flags flags, + size_t size) : + _bufferId(bufferId), _contextId(contextId), _flags(flags), _size(size) { +} + +CreateBuffer::CreateBuffer(const CreateBuffer& rhs) : + Request(rhs), _bufferId(rhs._bufferId), _contextId(rhs._contextId), + _flags(rhs._flags), _size(rhs._size) { +} + +dcl::object_id CreateBuffer::bufferId() const { + return _bufferId; +} + +dcl::object_id CreateBuffer::contextId() const { + return _contextId; +} + +cl_mem_flags CreateBuffer::flags() const { + return _flags; +} + +size_t CreateBuffer::size() const { + return _size; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CreateCommandQueue.cpp b/dclasio/src/dclasio/message/CreateCommandQueue.cpp new file mode 100644 index 0000000..86cd2d5 --- /dev/null +++ b/dclasio/src/dclasio/message/CreateCommandQueue.cpp @@ -0,0 +1,98 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file CreateCommandQueue.cpp + * + * @date 2011-05-31 + * @author Tunc Taylan Turunc + */ + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { +namespace message { + +CreateCommandQueue::CreateCommandQueue() { +} + +CreateCommandQueue::CreateCommandQueue(dcl::object_id contextId, + dcl::object_id deviceId, + dcl::object_id commandQueueId, + cl_command_queue_properties properties) : + _contextId(contextId), + _deviceId(deviceId), + _commandQueueId(commandQueueId), + _properties(properties) { +} + +CreateCommandQueue::CreateCommandQueue(const CreateCommandQueue& rhs) : Request(rhs), + _contextId(rhs._contextId), + _deviceId(rhs._deviceId), + _commandQueueId(rhs._commandQueueId), + _properties(rhs._properties) { +} + +dcl::object_id CreateCommandQueue::contextId() const { + return _contextId; +} + +dcl::object_id CreateCommandQueue::deviceId() const { + return _deviceId; +} + +dcl::object_id CreateCommandQueue::commandQueueId() const { + return _commandQueueId; +} + +cl_command_queue_properties CreateCommandQueue::properties() const { + return _properties; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CreateContext.cpp b/dclasio/src/dclasio/message/CreateContext.cpp new file mode 100644 index 0000000..07f78dc --- /dev/null +++ b/dclasio/src/dclasio/message/CreateContext.cpp @@ -0,0 +1,114 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateContext.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dclasio { + +namespace message { + +CreateContext::CreateContext() : + _contextId(0) { +} + +CreateContext::CreateContext( + dcl::object_id contextId, + const std::vector& computeNodeIds) : + _contextId(contextId), _computeNodeIds(computeNodeIds), + _deviceType(CL_DEVICE_TYPE_ALL) { +} + +CreateContext::CreateContext( + dcl::object_id contextId, + const std::vector& computeNodeIds, + cl_device_type deviceType) : + _contextId(contextId), _computeNodeIds(computeNodeIds), + _deviceType(deviceType) { +} + +CreateContext::CreateContext( + dcl::object_id contextId, + const std::vector& computeNodeIds, + const std::vector& deviceIds) : + _contextId(contextId), _computeNodeIds(computeNodeIds), + _deviceType(CL_DEVICE_TYPE_ALL), _deviceIds(deviceIds) { +} + +CreateContext::CreateContext(const CreateContext& rhs) : + Request(rhs), _contextId(rhs._contextId), + _computeNodeIds(rhs._computeNodeIds), + _deviceType(rhs._deviceType), _deviceIds(rhs._deviceIds) +{ +} + +dcl::object_id CreateContext::contextId() const { + return _contextId; +} + +const std::vector& CreateContext::computeNodeIds() const { + return _computeNodeIds; +} + +cl_device_type CreateContext::deviceType() const { + return _deviceType; +} + +const std::vector& CreateContext::deviceIds() const { + return _deviceIds; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CreateEvent.cpp b/dclasio/src/dclasio/message/CreateEvent.cpp new file mode 100644 index 0000000..8efb5d5 --- /dev/null +++ b/dclasio/src/dclasio/message/CreateEvent.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateEvent.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include + +namespace dclasio { +namespace message { + +CreateEvent::CreateEvent() { +} + +CreateEvent::CreateEvent(dcl::object_id contextId, + dcl::object_id eventId, + const std::vector& memObjectIds) : + _contextId(contextId), _eventId(eventId), _memObjectIds(memObjectIds) { +} + +CreateEvent::CreateEvent( + const CreateEvent& rhs) : + Request(rhs), _contextId(rhs._contextId), _eventId(rhs._eventId), + _memObjectIds(rhs._memObjectIds) { +} + +CreateEvent::~CreateEvent() { } + +dcl::object_id CreateEvent::contextId() const { + return _contextId; +} + +dcl::object_id CreateEvent::eventId() const { + return _eventId; +} + +const std::vector& CreateEvent::memObjectIds() const { + return _memObjectIds; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CreateKernel.cpp b/dclasio/src/dclasio/message/CreateKernel.cpp new file mode 100644 index 0000000..3cc50e2 --- /dev/null +++ b/dclasio/src/dclasio/message/CreateKernel.cpp @@ -0,0 +1,85 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateKernel.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include + +namespace dclasio { +namespace message { + +CreateKernel::CreateKernel() : + _kernelId(0), _programId(0) { +} + +CreateKernel::CreateKernel( + dcl::object_id kernelId, + dcl::object_id programId, + const char *kernelName) : + _kernelId(kernelId), _programId(programId), _kernelName(kernelName) { + assert(kernelName != nullptr && "Kernel name not specified"); +} + +CreateKernel::CreateKernel(const CreateKernel& rhs) : + Request(rhs), _kernelId(rhs._kernelId), _programId(rhs._programId), + _kernelName(rhs._kernelName) { +} + +dcl::object_id CreateKernel::kernelId() const { + return _kernelId; +} + +dcl::object_id CreateKernel::programId() const { + return _programId; +} + +const char * CreateKernel::kernelName() const { + return _kernelName.c_str(); +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CreateKernelsInProgram.cpp b/dclasio/src/dclasio/message/CreateKernelsInProgram.cpp new file mode 100644 index 0000000..448752e --- /dev/null +++ b/dclasio/src/dclasio/message/CreateKernelsInProgram.cpp @@ -0,0 +1,80 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateKernelsInProgram.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include +#include + +namespace dclasio { +namespace message { + +CreateKernelsInProgram::CreateKernelsInProgram( + dcl::object_id programId, + const std::vector& kernelIds) : + _programId(programId), _kernelIds(kernelIds) { +} + +CreateKernelsInProgram::CreateKernelsInProgram( + const CreateKernelsInProgram& rhs) : + Request(rhs), _programId(rhs._programId), _kernelIds(rhs._kernelIds) { +} + +CreateKernelsInProgram::CreateKernelsInProgram() : + _programId(0) { +} + +const std::vector& CreateKernelsInProgram::kernelIds() const { + return _kernelIds; +} + +dcl::object_id CreateKernelsInProgram::programId() const { + return _programId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/CreateProgramWithSource.cpp b/dclasio/src/dclasio/message/CreateProgramWithSource.cpp new file mode 100644 index 0000000..8c721fa --- /dev/null +++ b/dclasio/src/dclasio/message/CreateProgramWithSource.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file CreateProgramWithSource.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include + +namespace dclasio { +namespace message { + +CreateProgramWithSource::CreateProgramWithSource( + dcl::object_id programId, + dcl::object_id contextId, + size_t length) : + _programId(programId), _contextId(contextId), _length(length) { +} + +CreateProgramWithSource::CreateProgramWithSource( + const CreateProgramWithSource& rhs) : + Request(rhs), _programId(rhs._programId), _contextId(rhs._contextId), + _length(rhs._length) { +} + +CreateProgramWithSource::CreateProgramWithSource() : + _programId(0), _contextId(0), _length(0) { +} + +CreateProgramWithSource::~CreateProgramWithSource() { } + +dcl::object_id CreateProgramWithSource::programId() const { + return _programId; +} + +dcl::object_id CreateProgramWithSource::contextId() const { + return _contextId; +} + +size_t CreateProgramWithSource::length() const { + return _length; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeleteCommandQueue.cpp b/dclasio/src/dclasio/message/DeleteCommandQueue.cpp new file mode 100644 index 0000000..c1c71be --- /dev/null +++ b/dclasio/src/dclasio/message/DeleteCommandQueue.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteCommandQueue.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +DeleteCommandQueue::DeleteCommandQueue() : + _commandQueueId(0) { +} + +DeleteCommandQueue::DeleteCommandQueue( + dcl::object_id commandQueueId): + _commandQueueId(commandQueueId) { +} + +DeleteCommandQueue::DeleteCommandQueue( + const DeleteCommandQueue& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId) { +} + +DeleteCommandQueue::~DeleteCommandQueue() { } + +dcl::object_id DeleteCommandQueue::commandQueueId() const { + return _commandQueueId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeleteContext.cpp b/dclasio/src/dclasio/message/DeleteContext.cpp new file mode 100644 index 0000000..b46348a --- /dev/null +++ b/dclasio/src/dclasio/message/DeleteContext.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteContext.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +DeleteContext::DeleteContext() : + _contextId(0) { +} + +DeleteContext::DeleteContext( + dcl::object_id contextId) : + _contextId(contextId) { +} + +DeleteContext::DeleteContext( + const DeleteContext& rhs) : + Request(rhs), _contextId(rhs._contextId) { +} + +DeleteContext::~DeleteContext() { } + +dcl::object_id DeleteContext::contextId() const { + return _contextId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeleteEvent.cpp b/dclasio/src/dclasio/message/DeleteEvent.cpp new file mode 100644 index 0000000..c58f73a --- /dev/null +++ b/dclasio/src/dclasio/message/DeleteEvent.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteEvent.cpp + * + * \date 2011-07-11 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +DeleteEvent::DeleteEvent() : + _eventId(0) { +} + +DeleteEvent::DeleteEvent( + dcl::object_id eventId): + _eventId(eventId) { +} + +DeleteEvent::DeleteEvent( + const DeleteEvent& rhs) : + Request(rhs), _eventId(rhs._eventId) { +} + +DeleteEvent::~DeleteEvent() { } + +dcl::object_id DeleteEvent::eventId() const { + return _eventId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeleteKernel.cpp b/dclasio/src/dclasio/message/DeleteKernel.cpp new file mode 100644 index 0000000..6f6028b --- /dev/null +++ b/dclasio/src/dclasio/message/DeleteKernel.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteKernel.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +DeleteKernel::DeleteKernel() : + _kernelId(0) { +} + +DeleteKernel::DeleteKernel( + dcl::object_id kernelId) : + _kernelId(kernelId) { +} + +DeleteKernel::DeleteKernel( + const DeleteKernel& rhs) : + Request(rhs), _kernelId(rhs._kernelId) { +} + +DeleteKernel::~DeleteKernel() { } + +dcl::object_id DeleteKernel::kernelId() const { + return _kernelId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeleteMemory.cpp b/dclasio/src/dclasio/message/DeleteMemory.cpp new file mode 100644 index 0000000..0f722ab --- /dev/null +++ b/dclasio/src/dclasio/message/DeleteMemory.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteMemory.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +DeleteMemory::DeleteMemory() : + _memObjectId(0) { +} + +DeleteMemory::DeleteMemory( + dcl::object_id memObjectId) : + _memObjectId(memObjectId) { +} + +DeleteMemory::DeleteMemory( + const DeleteMemory& rhs) : + Request(rhs), _memObjectId(rhs._memObjectId) { +} + +DeleteMemory::~DeleteMemory() { } + +dcl::object_id DeleteMemory::memObjectId() const { + return _memObjectId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeleteProgram.cpp b/dclasio/src/dclasio/message/DeleteProgram.cpp new file mode 100644 index 0000000..2375076 --- /dev/null +++ b/dclasio/src/dclasio/message/DeleteProgram.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeleteProgram.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +DeleteProgram::DeleteProgram() : + _programId(0) { +} + +DeleteProgram::DeleteProgram(dcl::object_id programId) : + _programId(programId) { +} + +DeleteProgram::DeleteProgram(const DeleteProgram& rhs) : + Request(rhs), _programId(rhs._programId) { +} + +DeleteProgram::~DeleteProgram() { } + +dcl::object_id DeleteProgram::programId() const { + return _programId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeviceIDsResponse.h b/dclasio/src/dclasio/message/DeviceIDsResponse.h new file mode 100644 index 0000000..2829dec --- /dev/null +++ b/dclasio/src/dclasio/message/DeviceIDsResponse.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeviceIDsResponse.h + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#ifndef DEVICEIDSRESPONSE_H_ +#define DEVICEIDSRESPONSE_H_ + +#include +#include + +#include +#include + +#include + +namespace dclasio { + +namespace message { + +/*! + * \brief Response message containing a list of device IDs + */ +class DeviceIDsResponse: public DefaultResponse { +public: + DeviceIDsResponse() { + } + DeviceIDsResponse( + const Request& request, + const std::vector& deviceIds_) : + DefaultResponse(request), deviceIds(deviceIds_) { + } + DeviceIDsResponse(const DeviceIDsResponse& rhs) : + DefaultResponse(rhs), deviceIds(rhs.deviceIds) { + } + ~DeviceIDsResponse() { + } + + std::vector deviceIds; + + static const class_type TYPE = 200 + Request::GET_DEVICE_IDS; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + DefaultResponse::pack(buf); + buf << deviceIds; + } + + void unpack(dcl::ByteBuffer& buf) { + DefaultResponse::unpack(buf); + buf >> deviceIds; + } +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* DEVICEIDSRESPONSE_H_ */ diff --git a/dclasio/src/dclasio/message/DeviceInfosResponse.cpp b/dclasio/src/dclasio/message/DeviceInfosResponse.cpp new file mode 100644 index 0000000..4ff2f3b --- /dev/null +++ b/dclasio/src/dclasio/message/DeviceInfosResponse.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeviceInfosResponse.cpp + * + * \date 2011-05-19 + * \author Philipp Kegel + */ + +#include "DeviceInfosResponse.h" + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dclasio { + +namespace message { + +DeviceInfosResponse::DeviceInfosResponse() { +} + +DeviceInfosResponse::DeviceInfosResponse( + const Request& request, + const std::map& params) : + DefaultResponse(request), _params(params) { +} + +DeviceInfosResponse::DeviceInfosResponse( + const Request& request, + cl_device_info paramName, + size_t size, + const void *value) : + DefaultResponse(request) { + _params.insert(std::make_pair(paramName, dcl::Binary(size, value))); +} + +DeviceInfosResponse::DeviceInfosResponse( + const DeviceInfosResponse& rhs) : + DefaultResponse(rhs), _params(rhs._params) { +} + +DeviceInfosResponse::~DeviceInfosResponse() { } + +dcl::Binary DeviceInfosResponse::get_param( + cl_device_info paramName) const { + return _params.at(paramName); +} + +const std::map& DeviceInfosResponse::get_params() const { + return _params; +} + +} /* namespace message */ + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/DeviceInfosResponse.h b/dclasio/src/dclasio/message/DeviceInfosResponse.h new file mode 100644 index 0000000..f21a4ff --- /dev/null +++ b/dclasio/src/dclasio/message/DeviceInfosResponse.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file DeviceInfosResponse.h + * + * \date 2011-05-19 + * \author Philipp Kegel + */ + +#ifndef DEVICEINFOSRESPONSE_H_ +#define DEVICEINFOSRESPONSE_H_ + +#include +#include + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { + +namespace message { + +/*! + * \brief A response message containing a set of device information. + * + * Unlike InfoResponse, this class is designed to provide a set of information + * items rather than a single item. + * + * !!! This message class is currently not used. !!! + */ +class DeviceInfosResponse: public DefaultResponse { +public: + DeviceInfosResponse(); + DeviceInfosResponse( + const Request& request, + const std::map& params); + DeviceInfosResponse( + const Request& request, + cl_device_info paramName, + size_t size, + const void * value); + DeviceInfosResponse( + const DeviceInfosResponse& rhs); + virtual ~DeviceInfosResponse(); + + dcl::Binary get_param(cl_device_info paramName) const; + const std::map& get_params() const; + + static const class_type TYPE = 200 + Request::GET_DEVICE_INFO; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + DefaultResponse::pack(buf); + buf << _params; + } + + void unpack(dcl::ByteBuffer& buf) { + DefaultResponse::unpack(buf); + buf >> _params; + } + +private: + std::map _params; +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* DEVICEINFOSRESPONSE_H_ */ diff --git a/dclasio/src/dclasio/message/EnqueueBarrier.cpp b/dclasio/src/dclasio/message/EnqueueBarrier.cpp new file mode 100644 index 0000000..3f09856 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueBarrier.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueBarrier.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include + +namespace dclasio { +namespace message { + +EnqueueBarrier::EnqueueBarrier() { +} + +EnqueueBarrier::EnqueueBarrier( + dcl::object_id commandQueueId, + dcl::object_id commandId, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueBarrier::EnqueueBarrier(const EnqueueBarrier& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _commandId( + rhs._commandId), _eventIdWaitList(rhs._eventIdWaitList), _event( + rhs._event) { +} + +dcl::object_id EnqueueBarrier::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueBarrier::commandId() const { + return _commandId; +} + +const std::vector& EnqueueBarrier::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueBarrier::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueBroadcastBuffer.cpp b/dclasio/src/dclasio/message/EnqueueBroadcastBuffer.cpp new file mode 100644 index 0000000..2544c11 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueBroadcastBuffer.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueBroadcastBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include + +namespace dclasio { +namespace message { + +EnqueueBroadcastBuffer::EnqueueBroadcastBuffer() : + _commandId(0), _srcBufferId(0), _event(false) { +} + +EnqueueBroadcastBuffer::EnqueueBroadcastBuffer( + const std::vector& commandQueueIds, + dcl::object_id commandId, + dcl::object_id srcBufferId, + const std::vector& dstBufferIds, + size_t srcOffset, + const std::vector& dstOffsets, + size_t cb, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueIds(commandQueueIds), _commandId(commandId), + _srcBufferId(srcBufferId), _dstBufferIds(dstBufferIds), + _srcOffset(srcOffset), _dstOffsets(dstOffsets), _cb(cb), _event(event) +{ + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueBroadcastBuffer::EnqueueBroadcastBuffer(const EnqueueBroadcastBuffer& rhs) : + Request(rhs), _commandQueueIds(rhs._commandQueueIds), _commandId( + rhs._commandId), _srcBufferId(rhs._srcBufferId), _dstBufferIds( + rhs._dstBufferIds), _srcOffset(rhs._srcOffset), _dstOffsets( + rhs._dstOffsets), _cb(rhs._cb), _eventIdWaitList( + rhs._eventIdWaitList), _event(rhs._event) +{ +} + +const std::vector& EnqueueBroadcastBuffer::commandQueueIds() const { + return _commandQueueIds; +} + +dcl::object_id EnqueueBroadcastBuffer::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueBroadcastBuffer::srcBufferId() const { + return _srcBufferId; +} + +const std::vector& EnqueueBroadcastBuffer::dstBufferIds() const { + return _dstBufferIds; +} + +size_t EnqueueBroadcastBuffer::srcOffset() const { + return _srcOffset; +} + +const std::vector& EnqueueBroadcastBuffer::dstOffsets() const { + return _dstOffsets; +} + +size_t EnqueueBroadcastBuffer::cb() const { + return _cb; +} + +const std::vector& EnqueueBroadcastBuffer::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueBroadcastBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueCopyBuffer.cpp b/dclasio/src/dclasio/message/EnqueueCopyBuffer.cpp new file mode 100644 index 0000000..ea7b332 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueCopyBuffer.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueCopyBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include + +namespace dclasio { + +namespace message { + +EnqueueCopyBuffer::EnqueueCopyBuffer() : + _commandQueueId(0), _commandId(0), _srcBufferId(0), _dstBufferId(0), + _event(false) { +} + +EnqueueCopyBuffer::EnqueueCopyBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id srcBufferId, + dcl::object_id dstBufferId, + size_t srcOffset, + size_t dstOffset, + size_t cb, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), + _srcBufferId(srcBufferId), _dstBufferId(dstBufferId), + _srcOffset(srcOffset), _dstOffset(dstOffset), _cb(cb), _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueCopyBuffer::EnqueueCopyBuffer(const EnqueueCopyBuffer& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _commandId( + rhs._commandId), _srcBufferId(rhs._srcBufferId), _dstBufferId( + rhs._dstBufferId), _srcOffset(rhs._srcOffset), _dstOffset( + rhs._dstOffset), _cb(rhs._cb), _eventIdWaitList( + rhs._eventIdWaitList), _event(rhs._event) { +} + +dcl::object_id EnqueueCopyBuffer::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueCopyBuffer::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueCopyBuffer::srcBufferId() const { + return _srcBufferId; +} + +dcl::object_id EnqueueCopyBuffer::dstBufferId() const { + return _dstBufferId; +} + +size_t EnqueueCopyBuffer::srcOffset() const { + return _srcOffset; +} + +size_t EnqueueCopyBuffer::dstOffset() const { + return _dstOffset; +} + +size_t EnqueueCopyBuffer::cb() const { + return _cb; +} + +const std::vector& EnqueueCopyBuffer::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueCopyBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueMapBuffer.cpp b/dclasio/src/dclasio/message/EnqueueMapBuffer.cpp new file mode 100644 index 0000000..e9cbf0a --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueMapBuffer.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueMapBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { +namespace message { + +EnqueueMapBuffer::EnqueueMapBuffer() { +} + +EnqueueMapBuffer::EnqueueMapBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + bool blocking_read, + cl_map_flags map_flags, + size_t offset, + size_t cb, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _bufferId( + bufferId), _blocking(blocking_read), _mapFlags(map_flags), _offset( + offset), _cb(cb), _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueMapBuffer::EnqueueMapBuffer(const EnqueueMapBuffer& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _commandId( + rhs._commandId), _bufferId(rhs._bufferId), _blocking( + rhs._blocking), _mapFlags(rhs._mapFlags), _offset(rhs._offset), _cb( + rhs._cb), _eventIdWaitList(rhs._eventIdWaitList), _event( + rhs._event) { +} + +dcl::object_id EnqueueMapBuffer::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueMapBuffer::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueMapBuffer::bufferId() const { + return _bufferId; +} + +bool EnqueueMapBuffer::blocking() const { + return _blocking; +} + +cl_mem_flags EnqueueMapBuffer::mapFlags() const { + return _mapFlags; +} + +size_t EnqueueMapBuffer::offset() const { + return _offset; +} + +size_t EnqueueMapBuffer::cb() const { + return _cb; +} + +const std::vector& EnqueueMapBuffer::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueMapBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueMarker.cpp b/dclasio/src/dclasio/message/EnqueueMarker.cpp new file mode 100644 index 0000000..9b67ad8 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueMarker.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueMarker.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include + +namespace dclasio { +namespace message { + +EnqueueMarker::EnqueueMarker() { +} + +EnqueueMarker::EnqueueMarker( + dcl::object_id commandQueueId, + dcl::object_id commandId, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueMarker::EnqueueMarker(const EnqueueMarker& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _commandId( + rhs._commandId), _eventIdWaitList(rhs._eventIdWaitList), _event( + rhs._event) { +} + +dcl::object_id EnqueueMarker::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueMarker::commandId() const { + return _commandId; +} + +const std::vector& EnqueueMarker::eventIdWaitList(void) const { + return _eventIdWaitList; +} + +bool EnqueueMarker::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueNDRangeKernel.cpp b/dclasio/src/dclasio/message/EnqueueNDRangeKernel.cpp new file mode 100644 index 0000000..8843d59 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueNDRangeKernel.cpp @@ -0,0 +1,117 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueNDRangeKernel.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include +#include + +namespace dclasio { +namespace message { + +EnqueueNDRangeKernel::EnqueueNDRangeKernel() : + _commandQueueId(0), _commandId(0), _kernelId(0), _event(false) { +} + +EnqueueNDRangeKernel::EnqueueNDRangeKernel( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id kernelId, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _kernelId( + kernelId), _offset(offset), _global(global), _local(local), _event( + event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueNDRangeKernel::EnqueueNDRangeKernel(const EnqueueNDRangeKernel& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _commandId( + rhs._commandId), _kernelId(rhs._kernelId), _global(rhs._global), _local( + rhs._local), _eventIdWaitList(rhs._eventIdWaitList), _event( + rhs._event) { +} + +dcl::object_id EnqueueNDRangeKernel::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueNDRangeKernel::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueNDRangeKernel::kernelId() const { + return _kernelId; +} + +const std::vector& EnqueueNDRangeKernel::offset() const { + return _offset; +} + +const std::vector& EnqueueNDRangeKernel::global() const { + return _global; +} + +const std::vector& EnqueueNDRangeKernel::local() const { + return _local; +} + +const std::vector& EnqueueNDRangeKernel::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueNDRangeKernel::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueReadBuffer.cpp b/dclasio/src/dclasio/message/EnqueueReadBuffer.cpp new file mode 100644 index 0000000..bcb7091 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueReadBuffer.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueReadBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include + +namespace dclasio { +namespace message { + +EnqueueReadBuffer::EnqueueReadBuffer() : + _commandQueueId(0), _commandId(0), _bufferId(0), _event(false) { +} + +EnqueueReadBuffer::EnqueueReadBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + bool blocking_read, + size_t offset, + size_t cb, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _bufferId(bufferId), + _blocking(blocking_read), _offset(offset), _cb(cb), _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueReadBuffer::EnqueueReadBuffer( + const EnqueueReadBuffer& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), + _commandId(rhs._commandId), _bufferId(rhs._bufferId), + _blocking(rhs._blocking), _offset(rhs._offset), _cb(rhs._cb), + _eventIdWaitList(rhs._eventIdWaitList), _event(rhs._event) { +} + +dcl::object_id EnqueueReadBuffer::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueReadBuffer::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueReadBuffer::bufferId() const { + return _bufferId; +} + +bool EnqueueReadBuffer::blocking() const { + return _blocking; +} + +size_t EnqueueReadBuffer::offset() const { + return _offset; +} + +size_t EnqueueReadBuffer::cb() const { + return _cb; +} + +const std::vector& EnqueueReadBuffer::eventIdWaitList(void) const { + return _eventIdWaitList; +} + +bool EnqueueReadBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueReduceBuffer.cpp b/dclasio/src/dclasio/message/EnqueueReduceBuffer.cpp new file mode 100644 index 0000000..898eed6 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueReduceBuffer.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueReduceBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include +#include + +namespace dclasio { +namespace message { + +EnqueueReduceBuffer::EnqueueReduceBuffer() : + _commandId(0), _dstId(0), _kernelId(0), _event(false) { +} + +EnqueueReduceBuffer::EnqueueReduceBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + const std::vector& srcIds, + dcl::object_id dstId, + dcl::object_id kernelId, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _srcIds(srcIds), _dstId( + dstId), _kernelId(kernelId), _offset(offset), _global(global), _local( + local), _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueReduceBuffer::EnqueueReduceBuffer(const EnqueueReduceBuffer& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _commandId( + rhs._commandId), _srcIds(rhs._srcIds), _dstId(rhs._dstId), _kernelId( + rhs._kernelId), _global(rhs._global), _local(rhs._local), _eventIdWaitList( + rhs._eventIdWaitList), _event(rhs._event) { +} + +dcl::object_id EnqueueReduceBuffer::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueReduceBuffer::commandId() const { + return _commandId; +} + +const std::vector& EnqueueReduceBuffer::srcIds() const { + return _srcIds; +} + +dcl::object_id EnqueueReduceBuffer::dstId() const { + return _dstId; +} + +dcl::object_id EnqueueReduceBuffer::kernelId() const { + return _kernelId; +} + +const std::vector& EnqueueReduceBuffer::offset() const { + return _offset; +} + +const std::vector& EnqueueReduceBuffer::global() const { + return _global; +} + +const std::vector& EnqueueReduceBuffer::local() const { + return _local; +} + +const std::vector& EnqueueReduceBuffer::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueReduceBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueUnmapBuffer.cpp b/dclasio/src/dclasio/message/EnqueueUnmapBuffer.cpp new file mode 100644 index 0000000..0c3446c --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueUnmapBuffer.cpp @@ -0,0 +1,123 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueUnmapBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { +namespace message { + +EnqueueUnmapBuffer::EnqueueUnmapBuffer() { +} + +EnqueueUnmapBuffer::EnqueueUnmapBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + cl_map_flags map_flags, + size_t offset, + size_t cb, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _bufferId(bufferId), + _mapFlags(map_flags), _offset(offset), + _cb(cb), + _event(event) { + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueUnmapBuffer::EnqueueUnmapBuffer( + const EnqueueUnmapBuffer& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), + _commandId(rhs._commandId), _bufferId(rhs._bufferId), + _mapFlags(rhs._mapFlags), + _offset(rhs._offset), _cb(rhs._cb), + _eventIdWaitList(rhs._eventIdWaitList), _event(rhs._event) { +} + +dcl::object_id EnqueueUnmapBuffer::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueUnmapBuffer::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueUnmapBuffer::bufferId() const { + return _bufferId; +} + +cl_mem_flags EnqueueUnmapBuffer::mapFlags() const { + return _mapFlags; +} + +size_t EnqueueUnmapBuffer::offset() const { + return _offset; +} + +size_t EnqueueUnmapBuffer::cb() const { + return _cb; +} + +const std::vector& EnqueueUnmapBuffer::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueUnmapBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueWaitForEvents.cpp b/dclasio/src/dclasio/message/EnqueueWaitForEvents.cpp new file mode 100644 index 0000000..c43f685 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueWaitForEvents.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueWaitForEvents.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include + +namespace dclasio { +namespace message { + +EnqueueWaitForEvents::EnqueueWaitForEvents() { +} + +EnqueueWaitForEvents::EnqueueWaitForEvents( + dcl::object_id commandQueueId, + const std::vector& eventIdList) : + _commandQueueId(commandQueueId), _eventIdList(eventIdList) { +} + +EnqueueWaitForEvents::EnqueueWaitForEvents(const EnqueueWaitForEvents& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), _eventIdList( + rhs._eventIdList) { +} + +dcl::object_id EnqueueWaitForEvents::commandQueueId() const { + return _commandQueueId; +} + +const std::vector& EnqueueWaitForEvents::eventIdList() const { + return _eventIdList; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EnqueueWriteBuffer.cpp b/dclasio/src/dclasio/message/EnqueueWriteBuffer.cpp new file mode 100644 index 0000000..2e015a0 --- /dev/null +++ b/dclasio/src/dclasio/message/EnqueueWriteBuffer.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EnqueueWriteBuffer.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#include +#include + +namespace dclasio { +namespace message { + +EnqueueWriteBuffer::EnqueueWriteBuffer() : + _commandQueueId(0), _commandId(0), _bufferId(0), _event(false) { +} + +EnqueueWriteBuffer::EnqueueWriteBuffer( + dcl::object_id commandQueueId, + dcl::object_id commandId, + dcl::object_id bufferId, + bool blocking_write, + size_t offset, + size_t cb, + const std::vector *eventIdWaitList, + bool event) : + _commandQueueId(commandQueueId), _commandId(commandId), _bufferId(bufferId), + _blocking(blocking_write), _offset(offset), _cb(cb), _event(event) { + + if (eventIdWaitList) { + _eventIdWaitList = *eventIdWaitList; + } +} + +EnqueueWriteBuffer::EnqueueWriteBuffer(const EnqueueWriteBuffer& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId), + _commandId(rhs._commandId), _bufferId(rhs._bufferId), + _blocking(rhs._blocking), _offset(rhs._offset), _cb(rhs._cb), + _eventIdWaitList(rhs._eventIdWaitList), _event(rhs._event) { +} + +dcl::object_id EnqueueWriteBuffer::commandQueueId() const { + return _commandQueueId; +} + +dcl::object_id EnqueueWriteBuffer::commandId() const { + return _commandId; +} + +dcl::object_id EnqueueWriteBuffer::bufferId() const { + return _bufferId; +} + +bool EnqueueWriteBuffer::blocking() const { + return _blocking; +} + +size_t EnqueueWriteBuffer::offset() const { + return _offset; +} + +size_t EnqueueWriteBuffer::cb() const { + return _cb; +} + +const std::vector& EnqueueWriteBuffer::eventIdWaitList() const { + return _eventIdWaitList; +} + +bool EnqueueWriteBuffer::event() const { + return _event; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/ErrorResponse.cpp b/dclasio/src/dclasio/message/ErrorResponse.cpp new file mode 100644 index 0000000..1ba09f4 --- /dev/null +++ b/dclasio/src/dclasio/message/ErrorResponse.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ErrorResponse.cpp + * + * \date 2014-04-04 + * \author Philipp Kegel + */ + +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { +namespace message { + +class Request; + +/* ****************************************************************************/ + +ErrorResponse::ErrorResponse() : + _errcode(CL_SUCCESS) { +} + +ErrorResponse::ErrorResponse(const Request& request, cl_int errcode) : + Response(request), _errcode(errcode) { +} + +ErrorResponse::ErrorResponse(const ErrorResponse& rhs) : + Response(rhs), _errcode(rhs._errcode) { +} + +ErrorResponse::~ErrorResponse() { +} + +cl_int ErrorResponse::get_errcode() const { + return _errcode; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EventProfilingInfosResponse.cpp b/dclasio/src/dclasio/message/EventProfilingInfosResponse.cpp new file mode 100644 index 0000000..6b8d9a3 --- /dev/null +++ b/dclasio/src/dclasio/message/EventProfilingInfosResponse.cpp @@ -0,0 +1,82 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EventProfilingInfosResponse.cpp + * + * \date 2013-10-27 + * \author Philipp Kegel + */ + +#include + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { +namespace message { + +EventProfilingInfosReponse::EventProfilingInfosReponse() { +} + +EventProfilingInfosReponse::EventProfilingInfosReponse( + const Request& request, + cl_ulong received_, + cl_ulong queued_, + cl_ulong submit_, + cl_ulong start_, + cl_ulong end_) : + DefaultResponse(request), received(received_), queued(queued_), submit( + submit_), start(start_), end(end_) { +} + +EventProfilingInfosReponse::EventProfilingInfosReponse( + const EventProfilingInfosReponse& rhs) : + DefaultResponse(rhs), received(rhs.received), queued(rhs.queued), submit( + rhs.submit), start(rhs.start), end(rhs.end) { +} + +EventProfilingInfosReponse::~EventProfilingInfosReponse() { +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/EventSynchronizationMessage.cpp b/dclasio/src/dclasio/message/EventSynchronizationMessage.cpp new file mode 100644 index 0000000..da8140a --- /dev/null +++ b/dclasio/src/dclasio/message/EventSynchronizationMessage.cpp @@ -0,0 +1,76 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file EventSynchronizationMessage.cpp + * + * \date 2014-04-03 + * \author Philipp Kegel + */ + +#include + +#include +#include + +namespace dclasio { + +namespace message { + +EventSynchronizationMessage::EventSynchronizationMessage() : + _commandId(0) { +} + +EventSynchronizationMessage::EventSynchronizationMessage( + dcl::object_id commandId) : + _commandId(commandId) { +} + +EventSynchronizationMessage::EventSynchronizationMessage( + const EventSynchronizationMessage& rhs) : + _commandId(rhs._commandId) { +} + +EventSynchronizationMessage::~EventSynchronizationMessage() { +} + +dcl::object_id EventSynchronizationMessage::commandId() const { + return _commandId; +} + +} /* namespace message */ + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/FinishRequest.cpp b/dclasio/src/dclasio/message/FinishRequest.cpp new file mode 100644 index 0000000..f1cdb01 --- /dev/null +++ b/dclasio/src/dclasio/message/FinishRequest.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file FinishRequest.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +FinishRequest::FinishRequest() : + _commandQueueId(0) { +} + +FinishRequest::FinishRequest(dcl::object_id commandQueueId) : + _commandQueueId(commandQueueId) { +} + +FinishRequest::FinishRequest(const FinishRequest& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId) { +} + +FinishRequest::~FinishRequest() { +} + +dcl::object_id FinishRequest::commandQueueId() const { + return _commandQueueId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/FlushRequest.cpp b/dclasio/src/dclasio/message/FlushRequest.cpp new file mode 100644 index 0000000..a02b3d5 --- /dev/null +++ b/dclasio/src/dclasio/message/FlushRequest.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file FlushRequest.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +FlushRequest::FlushRequest() : + _commandQueueId(0) { +} + +FlushRequest::FlushRequest(dcl::object_id commandQueueId) : + _commandQueueId(commandQueueId) { +} + +FlushRequest::FlushRequest(const FlushRequest& rhs) : + Request(rhs), _commandQueueId(rhs._commandQueueId) { +} + +FlushRequest::~FlushRequest() { +} + +dcl::object_id FlushRequest::commandQueueId() const { + return _commandQueueId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/GetDeviceIDs.h b/dclasio/src/dclasio/message/GetDeviceIDs.h new file mode 100644 index 0000000..a14b51f --- /dev/null +++ b/dclasio/src/dclasio/message/GetDeviceIDs.h @@ -0,0 +1,96 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetDeviceIDs.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef GETDEVICEIDS_H_ +#define GETDEVICEIDS_H_ + +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { +namespace message { + +class GetDeviceIDs: public Request { +public: + GetDeviceIDs() : + deviceType(CL_DEVICE_TYPE_ALL) { + } + GetDeviceIDs(cl_device_type deviceType_) : + deviceType(deviceType_) { + } + GetDeviceIDs(const GetDeviceIDs& rhs) : + Request(rhs), deviceType(rhs.deviceType) { + } + virtual ~GetDeviceIDs() { + } + + cl_device_type deviceType; + + static const class_type TYPE = 100 + GET_DEVICE_IDS; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << deviceType; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> deviceType; + } +}; + +} /* namespace message */ +} /* namespace dclasio */ + +#endif /* GETDEVICEIDS_H_ */ diff --git a/dclasio/src/dclasio/message/GetDeviceInfo.h b/dclasio/src/dclasio/message/GetDeviceInfo.h new file mode 100644 index 0000000..1f041bc --- /dev/null +++ b/dclasio/src/dclasio/message/GetDeviceInfo.h @@ -0,0 +1,103 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetDeviceInfo.h + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#ifndef GETDEVICEINFO_H_ +#define GETDEVICEINFO_H_ + +#include + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +namespace message { + +/*! + * \brief A message for requesting a single piece of device information. + */ +class GetDeviceInfo: public Request { +public: + GetDeviceInfo() : + deviceId(0), paramName(CL_DEVICE_NAME) { + } + GetDeviceInfo(dcl::object_id deviceId_, cl_device_info paramName_) : + deviceId(deviceId_), paramName(paramName_) { + } + GetDeviceInfo(const GetDeviceInfo& rhs) : + Request(rhs), deviceId(rhs.deviceId), paramName(rhs.paramName) { + } + virtual ~GetDeviceInfo() { + } + + dcl::object_id deviceId; + cl_device_info paramName; + + static const class_type TYPE = 100 + GET_DEVICE_INFO; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + Request::pack(buf); + buf << deviceId << paramName; + } + + void unpack(dcl::ByteBuffer& buf) { + Request::unpack(buf); + buf >> deviceId >> paramName; + } +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* GETDEVICEINFO_H_ */ diff --git a/dclasio/src/dclasio/message/GetEventProfilingInfos.cpp b/dclasio/src/dclasio/message/GetEventProfilingInfos.cpp new file mode 100644 index 0000000..c9915dd --- /dev/null +++ b/dclasio/src/dclasio/message/GetEventProfilingInfos.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetEventProfilingInfos.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +namespace dclasio { +namespace message { + +GetEventProfilingInfos::GetEventProfilingInfos() { +} + +GetEventProfilingInfos::GetEventProfilingInfos( + dcl::object_id eventID) : _eventId(eventID) { +} + +GetEventProfilingInfos::GetEventProfilingInfos(const GetEventProfilingInfos& rhs) : + _eventId(rhs._eventId) { +} + +GetEventProfilingInfos::~GetEventProfilingInfos() { } + +dcl::object_id GetEventProfilingInfos::eventId() const { + return _eventId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/GetKernelInfo.cpp b/dclasio/src/dclasio/message/GetKernelInfo.cpp new file mode 100644 index 0000000..2c7ae7c --- /dev/null +++ b/dclasio/src/dclasio/message/GetKernelInfo.cpp @@ -0,0 +1,126 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file GetKernelInfo.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +/* **************************************************************************** + * Get kernel info + ******************************************************************************/ + +namespace dclasio { +namespace message { + +GetKernelInfo::GetKernelInfo() { +} + +GetKernelInfo::GetKernelInfo(dcl::object_id kernelId, cl_kernel_info paramName) : + _kernelId(kernelId), _paramName(paramName) { +} + +GetKernelInfo::GetKernelInfo(const GetKernelInfo& rhs) : + Request(rhs), _kernelId(rhs._kernelId), _paramName(rhs._paramName) { +} + +GetKernelInfo::~GetKernelInfo() { +} + +dcl::object_id GetKernelInfo::kernelId() const { + return _kernelId; +} + +cl_kernel_info GetKernelInfo::paramName() const { + return _paramName; +} + +} /* namespace message */ +} /* namespace dclasio */ + +/* **************************************************************************** + * Get kernel work group info + ******************************************************************************/ + +namespace dclasio { +namespace message { + +GetKernelWorkGroupInfo::GetKernelWorkGroupInfo() { +} + +GetKernelWorkGroupInfo::GetKernelWorkGroupInfo( + dcl::object_id kernelId, + dcl::object_id deviceId, + cl_kernel_work_group_info paramName) : + _kernelId(kernelId), _deviceId(deviceId), _paramName(paramName) { +} + +GetKernelWorkGroupInfo::GetKernelWorkGroupInfo( + const GetKernelWorkGroupInfo& rhs) : + Request(rhs), _kernelId(rhs._kernelId), _deviceId(rhs._deviceId), _paramName( + rhs._paramName) { +} + +GetKernelWorkGroupInfo::~GetKernelWorkGroupInfo() { +} + +dcl::object_id GetKernelWorkGroupInfo::kernelId() const { + return _kernelId; +} + +dcl::object_id GetKernelWorkGroupInfo::deviceId() const { + return _deviceId; +} + +cl_kernel_info GetKernelWorkGroupInfo::paramName() const { + return _paramName; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/InfoResponse.cpp b/dclasio/src/dclasio/message/InfoResponse.cpp new file mode 100644 index 0000000..2ef83a8 --- /dev/null +++ b/dclasio/src/dclasio/message/InfoResponse.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file InfoResponse.cpp + * + * \date 2011-05-19 + * \author Philipp Kegel + */ + +#include +#include +#include + +#include + +#include + +namespace dclasio { +namespace message { + +InfoResponse::InfoResponse() { +} + +InfoResponse::InfoResponse( + const Request& request, + size_t size, + const void *value) : + DefaultResponse(request), _param(size, value) { +} + +InfoResponse::InfoResponse( + const InfoResponse& rhs) : + DefaultResponse(rhs), _param(rhs._param) { +} + +InfoResponse::~InfoResponse() { } + +dcl::Binary InfoResponse::param() const { + return _param; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/Message.cpp b/dclasio/src/dclasio/message/Message.cpp new file mode 100644 index 0000000..6f04d8c --- /dev/null +++ b/dclasio/src/dclasio/message/Message.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Message.cpp + * + * \date 2014-03-26 + * \author Philipp Kegel + */ + +#include "ContextErrorMessage.h" +#include "DeviceIDsResponse.h" +#include "DeviceInfosResponse.h" +#include "GetDeviceIDs.h" +#include "GetDeviceInfo.h" +#include "ProgramBuildMessage.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace dclasio { +namespace message { + +Message * createMessage(Message::class_type type) { + // TODO Register message classes to associate message type ID and message class automatically + switch (type) + { + // event messages + case CommandExecutionStatusChangedMessage::TYPE: + return new CommandExecutionStatusChangedMessage(); + case ContextErrorMessage::TYPE: return new ContextErrorMessage(); + case EventSynchronizationMessage::TYPE: return new EventSynchronizationMessage(); + case ProgramBuildMessage::TYPE: return new ProgramBuildMessage(); + + // request messages + case BuildProgram::TYPE: return new BuildProgram(); + case CreateBuffer::TYPE: return new CreateBuffer(); + case CreateCommandQueue::TYPE: return new CreateCommandQueue(); + case CreateContext::TYPE: return new CreateContext(); + case CreateEvent::TYPE: return new CreateEvent(); + case CreateKernel::TYPE: return new CreateKernel(); + case CreateKernelsInProgram::TYPE: return new CreateKernelsInProgram(); + // TODO Implement CreateProgramWithBinary message +// case CreateProgramWithBinary::TYPE: return new CreateProgramWithBinary(); + case CreateProgramWithSource::TYPE: return new CreateProgramWithSource(); + case DeleteCommandQueue::TYPE: return new DeleteCommandQueue(); + case DeleteContext::TYPE: return new DeleteContext(); + case DeleteEvent::TYPE: return new DeleteEvent(); + case DeleteKernel::TYPE: return new DeleteKernel(); + case DeleteMemory::TYPE: return new DeleteMemory(); + case DeleteProgram::TYPE: return new DeleteProgram(); + case EnqueueBarrier::TYPE: return new EnqueueBarrier(); + case EnqueueBroadcastBuffer::TYPE: return new EnqueueBroadcastBuffer(); + case EnqueueCopyBuffer::TYPE: return new EnqueueCopyBuffer(); + case EnqueueMapBuffer::TYPE: return new EnqueueMapBuffer(); + case EnqueueMarker::TYPE: return new EnqueueMarker(); + case EnqueueNDRangeKernel::TYPE: return new EnqueueNDRangeKernel(); + case EnqueueReadBuffer::TYPE: return new EnqueueReadBuffer(); + case EnqueueReduceBuffer::TYPE: return new EnqueueReduceBuffer(); + case EnqueueUnmapBuffer::TYPE: return new EnqueueUnmapBuffer(); + case EnqueueWaitForEvents::TYPE: return new EnqueueWaitForEvents(); + case EnqueueWriteBuffer::TYPE: return new EnqueueWriteBuffer(); + case FinishRequest::TYPE: return new FinishRequest(); + case FlushRequest::TYPE: return new FlushRequest(); + case GetDeviceIDs::TYPE: return new GetDeviceIDs(); + case GetDeviceInfo::TYPE: return new GetDeviceInfo(); + case GetEventProfilingInfos::TYPE: return new GetEventProfilingInfos(); + case GetKernelInfo::TYPE: return new GetKernelInfo(); + case GetKernelWorkGroupInfo::TYPE: return new GetKernelWorkGroupInfo(); + // TODO Implement GetProgramBuildLog message +// case GetProgramBuildLog::TYPE: return new GetProgramBuildLog(); + case SetKernelArg::TYPE: return new SetKernelArg(); + case SetKernelArgBinary::TYPE: return new SetKernelArgBinary(); + case SetKernelArgMemObject::TYPE: return new SetKernelArgMemObject(); + + // response messages + case DefaultResponse::TYPE: return new DefaultResponse(); + case DeviceIDsResponse::TYPE: return new DeviceIDsResponse(); + case DeviceInfosResponse::TYPE: return new DeviceInfosResponse(); + case EventProfilingInfosReponse::TYPE: return new EventProfilingInfosReponse(); + case ErrorResponse::TYPE: return new ErrorResponse(); + case InfoResponse::TYPE: return new InfoResponse(); + + default: + throw std::invalid_argument("Invalid message type"); + /* no break */ + } +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/ProgramBuildMessage.h b/dclasio/src/dclasio/message/ProgramBuildMessage.h new file mode 100644 index 0000000..311793e --- /dev/null +++ b/dclasio/src/dclasio/message/ProgramBuildMessage.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProgramBuildMessage.h + * + * Messages regarding program build. + * + * \date 2011-12-23 + * \author Philipp Kegel + */ + +#ifndef PROGRAMBUILDMESSAGE_H_ +#define PROGRAMBUILDMESSAGE_H_ + +#include + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclasio { + +namespace message { + +/** + * @brief Notification of completion of program build. + * + * This message is sent from compute nodes to the host to indicate completion of program build. + * The build status of each device is returned. + */ +class ProgramBuildMessage: public Message { +public: + ProgramBuildMessage() { + } + + ProgramBuildMessage( + dcl::object_id programId_, + const std::vector& deviceIds_, + const std::vector& buildStatus_): + programBuildId(programId_), deviceIds(deviceIds_), buildStatus(buildStatus_) { + } + + ProgramBuildMessage( + const ProgramBuildMessage& rhs) : + programBuildId(rhs.programBuildId), deviceIds(rhs.deviceIds), + buildStatus(rhs.buildStatus) { + } + + ~ProgramBuildMessage() { } + + dcl::object_id programBuildId; + std::vector deviceIds; + std::vector buildStatus; + + static const class_type TYPE = 701; + + class_type get_type() const { + return TYPE; + } + + void pack(dcl::ByteBuffer& buf) const { + buf << programBuildId << deviceIds << buildStatus; + } + + void unpack(dcl::ByteBuffer& buf) { + buf >> programBuildId >> deviceIds >> buildStatus; + } +}; + +} /* namespace message */ + +} /* namespace dclasio */ + +#endif /* PROGRAMBUILDMESSAGE_H_ */ diff --git a/dclasio/src/dclasio/message/ReleaseRequest.cpp b/dclasio/src/dclasio/message/ReleaseRequest.cpp new file mode 100644 index 0000000..49a774e --- /dev/null +++ b/dclasio/src/dclasio/message/ReleaseRequest.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ReleaseRequest.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#if 0 +#include +#include + +#include + +namespace dclasio { +namespace message { + +template +ReleaseRequest::ReleaseRequest() : + _objectId(0) { +} + +template +ReleaseRequest::ReleaseRequest(dcl::object_id objectId) : + _objectId(objectId) { +} + +template +ReleaseRequest::ReleaseRequest(const ReleaseRequest& rhs) : + Request(rhs), _objectId(rhs._objectId) { +} + +template +ReleaseRequest::~ReleaseRequest() { +} + +/* ****************************************************************************/ + +/* Explicit template instantiations */ +template class ReleaseRequest; +template class ReleaseRequest; +template class ReleaseRequest; +template class ReleaseRequest; +template class ReleaseRequest; +template class ReleaseRequest; + +} /* namespace message */ +} /* namespace dclasio */ +#endif diff --git a/dclasio/src/dclasio/message/Request.cpp b/dclasio/src/dclasio/message/Request.cpp new file mode 100644 index 0000000..b536d44 --- /dev/null +++ b/dclasio/src/dclasio/message/Request.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Request.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include + +namespace dclasio { +namespace message { + +Request::id_type Request::requestCount = 0; + +Request::Request() : + id(++requestCount) { +} + +Request::Request(const Request& rhs) : + id(rhs.id) { +} + +Request::~Request() { +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/Response.cpp b/dclasio/src/dclasio/message/Response.cpp new file mode 100644 index 0000000..a04e1d6 --- /dev/null +++ b/dclasio/src/dclasio/message/Response.cpp @@ -0,0 +1,98 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Response.cpp + * + * \date 2011-04-08 + * \author Philipp Kegel + */ + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclasio { + +namespace message { + +Response::Response() : + _requestId(0) { +} + +Response::Response(const Request& request) : + _requestId(request.id) { +} + +Response::Response(const Response& rhs) : + _requestId(rhs._requestId) { +} + +Response::~Response() { +} + +Request::id_type Response::get_request_id() const { + return _requestId; +} + +/* ****************************************************************************/ + +DefaultResponse::DefaultResponse() { +} + +DefaultResponse::DefaultResponse(const Request& request) : + Response(request) { +} + +DefaultResponse::DefaultResponse(const DefaultResponse& rhs) : + Response(rhs) { +} + +DefaultResponse::~DefaultResponse() { +} + +cl_int DefaultResponse::get_errcode() const { + return CL_SUCCESS; +} + +} /* namespace message */ + +} /* namespace dclasio */ diff --git a/dclasio/src/dclasio/message/SetKernelArg.cpp b/dclasio/src/dclasio/message/SetKernelArg.cpp new file mode 100644 index 0000000..1358d1a --- /dev/null +++ b/dclasio/src/dclasio/message/SetKernelArg.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \!file SetKernelArg.cpp + * + * \date 2014-04-05 + * \author Philipp Kegel + */ + +#include +#include + +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclasio { +namespace message { + +/* **************************************************************************** + * Set kernel argument + ******************************************************************************/ + +SetKernelArg::SetKernelArg() : + _kernelId(0) { +} + +SetKernelArg::SetKernelArg(dcl::object_id kernelId, cl_uint index) : + _kernelId(kernelId), _index(index) { +} + +SetKernelArg::SetKernelArg(const SetKernelArg& rhs) : + Request(rhs), _kernelId(rhs._kernelId), _index(rhs._index) { +} + +SetKernelArg::~SetKernelArg() { +} + +dcl::object_id SetKernelArg::kernelId() const { + return _kernelId; +} + +cl_uint SetKernelArg::argIndex() const { + return _index; +} + +/* **************************************************************************** + * Set binary kernel argument + ******************************************************************************/ + +SetKernelArgBinary::SetKernelArgBinary() { +} + +SetKernelArgBinary::SetKernelArgBinary( + dcl::object_id kernelId, + cl_uint index, + size_t size, + const void *value) : + SetKernelArg(kernelId, index), _arg(size, value) { +} + +SetKernelArgBinary::SetKernelArgBinary(const SetKernelArgBinary& rhs) : + SetKernelArg(rhs), _arg(rhs._arg) { +} + +SetKernelArgBinary::~SetKernelArgBinary() { +} + +size_t SetKernelArgBinary::argSize() const { + return _arg.size(); +} + +const void * SetKernelArgBinary::argValue() const { + return _arg.value(); +} + +/* **************************************************************************** + * Set memory object as kernel argument + ******************************************************************************/ + +SetKernelArgMemObject::SetKernelArgMemObject() : + _memObjectId(0) { +} + +SetKernelArgMemObject::SetKernelArgMemObject( + dcl::object_id kernelId, + cl_uint index, + size_t size) : + SetKernelArg(kernelId, index), _size(size), _memObjectId(0) { +} + +SetKernelArgMemObject::SetKernelArgMemObject( + dcl::object_id kernelId, + cl_uint index, + dcl::object_id memObjectId) : + SetKernelArg(kernelId, index), _size(sizeof(cl_mem)), _memObjectId( + memObjectId) { +} + +SetKernelArgMemObject::SetKernelArgMemObject(const SetKernelArgMemObject& rhs) : + SetKernelArg(rhs), _size(rhs._size), _memObjectId(rhs._memObjectId) { +} + +SetKernelArgMemObject::~SetKernelArgMemObject() { +} + +size_t SetKernelArgMemObject::argSize() const { + return _size; +} + +const void * SetKernelArgMemObject::argValue() const { + return (_memObjectId == 0) ? nullptr : &_memObjectId; +} + +dcl::object_id SetKernelArgMemObject::memObjectId() const { + return _memObjectId; +} + +} /* namespace message */ +} /* namespace dclasio */ diff --git a/icdpp/CMakeLists.txt b/icdpp/CMakeLists.txt new file mode 100644 index 0000000..b424140 --- /dev/null +++ b/icdpp/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 2.6) + +project(dOpenCLicd) + +option(USE_MEM_LOCK "Use page-locked host memory (experimental, Linux only)" OFF) + +set(DOPENCL_INCLUDE_DIR "${dOpenCLlib_SOURCE_DIR}/include" CACHE PATH "Path to dOpenCL headers") +set(DOPENCL_LIBRARY_DIR "${dOpenCLlib_BINARY_DIR}" CACHE PATH "Path to dOpenCL library") + +# search for Boost String Algorithms Library +find_package(Boost 1.32.0 REQUIRED) + +file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src *.cpp) +#aux_source_directory(${PROJECT_SOURCE_DIR}/src SOURCES) + +include_directories(${DOPENCL_INCLUDE_DIR} + ${Boost_INCLUDE_DIRS}) + +link_directories(${DOPENCL_LIBRARY_DIR} + ${Boost_LIBRARY_DIRS}) + +# +# dOpenCL ICD target +# + +add_library (dOpenCL SHARED ${SOURCES}) +# TODO Library type must be 'MODULE', such that it can be plugged into the ICD loader using dlopen-like functionality +#add_library (dOpenCL MODULE ${SOURCES}) +target_link_libraries (dOpenCL + dcl + ${Boost_LIBRARIES}) + +# enable OpenCL 1.1 compatibility +set_property(TARGET dOpenCL + PROPERTY COMPILE_DEFINITIONS + CL_USE_DEPRECATED_OPENCL_1_1_APIS) +if(USE_MEM_LOCK) +set_property(TARGET dOpenCL + APPEND PROPERTY COMPILE_DEFINITIONS + DCL_MEM_LOCK) +endif(USE_MEM_LOCK) +# bind references to global symbols to the definition within the shared library (obsolete); +# set library version and SONAME +set_target_properties(dOpenCL PROPERTIES +# LINK_FLAGS -Bsymbolic-functions + VERSION 0.4.0 + SOVERSION 0) + +if(UNIX) +# TODO Create vendor file for ICD loader (UNIX only) + # File will be placed in /etc/OpenCL/vendors during installation + #file(WRITE wwu.icd "$") +endif(UNIX) +if(WIN32) +#TODO Create registry entry for ICD loader (Windows only) +endif(WIN32) + + +# +# install configuration +# + +install(TARGETS dOpenCL + DESTINATION lib) diff --git a/icdpp/src/CommandQueue.cpp b/icdpp/src/CommandQueue.cpp new file mode 100644 index 0000000..ee61a0a --- /dev/null +++ b/icdpp/src/CommandQueue.cpp @@ -0,0 +1,1007 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file CommandQueue.cpp + * + * @date 2011-05-31 + * @author Karsten Jeschkies + * @author Philipp Kegel + */ + +#include "CommandQueue.h" + +#include "Context.h" +#include "Device.h" +#include "Event.h" +#include "Kernel.h" +#include "Memory.h" +#include "Platform.h" +#include "Program.h" +#include "Retainable.h" + +#include "dclicd/Buffer.h" +#include "dclicd/Error.h" +#include "dclicd/Event.h" +#include "dclicd/utility.h" + +#include "dclicd/command/Command.h" +#include "dclicd/command/ReadWriteCommand.h" +#include "dclicd/command/MappingCommand.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#include +#include +#else +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +_cl_command_queue::_cl_command_queue(cl_context context, cl_device_id device, + cl_command_queue_properties properties) : + _context(context), _device(device), _properties(properties) +{ + if (!context) throw dclicd::Error(CL_INVALID_CONTEXT); + if (!device) throw dclicd::Error(CL_INVALID_DEVICE); + if (!context->hasDevice(device)) throw dclicd::Error(CL_INVALID_DEVICE); + + try { + dclasio::message::CreateCommandQueue request(_context->remoteId(), + _device->remote().getId(), _id, properties); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Command queue created (ID=" << _id << ')' << std::endl; + + /* Register command queue as command queue listener listener */ + _context->getPlatform()->remote().objectRegistry().bind(_id, *this); + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + _context->retain(); +} + +_cl_command_queue::~_cl_command_queue() { + dclicd::release(_context); +} + +void _cl_command_queue::destroy() { + assert(_ref_count == 0); + + /* A command queue must only be deleted if their reference count is 0 *and* + * all commands enqueued to it have finished. + * + * Note that the command queue on the host does not have to be retained + * for commands that have only been enqueued remotely as the remote command + * queue is implicitly retained by the compute node's OpenCL implementation. */ + finishLocally(); + + try { + dclasio::message::DeleteCommandQueue request(_id); + _device->remote().getComputeNode().executeCommand(request); + + /* Remove this command queue from list of command queue listeners */ + _context->getPlatform()->remote().objectRegistry().unbind(_id); + + dcl::util::Logger << dcl::util::Info + << "Command queue deleted (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +dcl::ComputeNode& _cl_command_queue::computeNode() const { + return _device->remote().getComputeNode(); +} + +void _cl_command_queue::getInfo( + cl_command_queue_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_QUEUE_CONTEXT: + dclicd::copy_info(_context, param_value_size, + param_value, param_value_size_ret); + break; + case CL_QUEUE_DEVICE: + dclicd::copy_info(_device, param_value_size, + param_value, param_value_size_ret); + break; + case CL_QUEUE_REFERENCE_COUNT: + dclicd::copy_info(_ref_count, param_value_size, + param_value, param_value_size_ret); + break; + case CL_QUEUE_PROPERTIES: + dclicd::copy_info(_properties, param_value_size, + param_value, param_value_size_ret); + break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +void _cl_command_queue::finish() { + try { + dclasio::message::FinishRequest request(_id); + + /* TODO Make _cl_command_queue::finish a non-blocking operation. + * Finishing may block for a long time on the compute node. Hence, the + * client driver must not report an IO exception, if no response is + * received from the compute node immediately. */ +// _device->remote().getComputeNode().executeCommand(request, dclasio::message::Request::BLOCKING); + _device->remote().getComputeNode().executeCommand(request); + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + /* TODO Make compute node call _cl_command_queue::onFinish */ + onFinish(); + + dcl::util::Logger << dcl::util::Info + << "Finished command queue (ID=" << _id << ')' << std::endl; +} + +void _cl_command_queue::onFinish() { + finishLocally(); +} + +void _cl_command_queue::flush() { + try { + dclasio::message::FlushRequest request(_id); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Flushed command queue (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_command_queue::createEventIdWaitList( + const std::vector& event_wait_list, + std::vector& eventIds) { + eventIds.resize(event_wait_list.size()); + for (unsigned int i = 0; i < event_wait_list.size(); ++i) { + cl_event event = event_wait_list[i]; + cl_context context; + + if (!event) throw dclicd::Error(CL_INVALID_EVENT_WAIT_LIST); + /* Command queue and event must be associated with the same context */ + event->getInfo(CL_EVENT_CONTEXT, sizeof(context), &context, nullptr); + if (context != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + eventIds[i] = event->remoteId(); + } +} + +void _cl_command_queue::enqueueCommand( + const std::shared_ptr& command) { + std::lock_guard lock(_commandsMutex); + /* Remove completed commands from list */ + _commands.erase( + std::remove_if(std::begin(_commands), std::end(_commands), + std::bind(&dclicd::command::Command::isComplete, std::placeholders::_1)), + std::end(_commands)); + /* Add command to list */ + _commands.push_back(command); +} + +void _cl_command_queue::finishLocally() { + std::vector> commands; + + /* Clean up command queue */ + { + std::lock_guard lock(_commandsMutex); + /* clear list of enqueued command */ + commands.swap(_commands); + } + + /* Wait until all pending commands have finished */ + dcl::util::Logger << dcl::util::Debug + << "Waiting for " << commands.size() << " commands in queue (ID=" << _id << ')' + << std::endl; + for (auto command : commands) { + command->wait(); + } +} + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +void _cl_command_queue::enqueueWaitForEvents( + const std::vector& eventList) { + std::vector eventIds; + + if (eventList.empty()) throw dclicd::Error(CL_INVALID_VALUE); + + /* + * Convert event list + * Unlike an event wait list, the event list of this method must not contain + * user events. Moreover, it throws CL_INVALID_EVENT rather than + * CL_INVALID_EVENT_WAIT_LIST if the event list contains an invalid event. + */ + eventIds.resize(eventList.size()); + for (unsigned int i = 0; i < eventList.size(); ++i) { + cl_event event = eventList[i]; + cl_context context; + + if (!event) throw dclicd::Error(CL_INVALID_EVENT); + /* Command queue and event must be associated with the same context */ + event->getInfo(CL_EVENT_CONTEXT, sizeof(context), &context, nullptr); + if (context != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + eventIds[i] = event->remoteId(); + } + + /* + * Enqueue wait for events command on command queue's compute node + */ + try { + dclasio::message::EnqueueWaitForEvents request(_id, eventIds); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued wait for events (command queue ID=" << _id << ')' + << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +void _cl_command_queue::enqueueMarker( + const std::vector& event_wait_list, cl_event *event) { + std::vector eventIds; + + /* Convert event wait list */ + createEventIdWaitList(event_wait_list, eventIds); + + /* Create event */ + if (event) { + std::shared_ptr marker( + std::make_shared(CL_COMMAND_MARKER, this)); + enqueueCommand(marker); + *event = new dclicd::Event(_context, marker); +// *event = new dclicd::Event(_context, this, CL_COMMAND_MARKER); + } + + /* + * Enqueue marker on command queue's compute node + */ + try { + dclasio::message::EnqueueMarker request(_id, (event ? (*event)->remoteId() : 0), + &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued marker (command queue ID=" << _id + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_command_queue::enqueueBarrier( + const std::vector& event_wait_list, cl_event *event) { + std::vector eventIds; + + /* Convert event wait list */ + createEventIdWaitList(event_wait_list, eventIds); + + /* Create event */ + if (event) { + std::shared_ptr barrier( + std::make_shared(CL_COMMAND_BARRIER, this)); + enqueueCommand(barrier); + *event = new dclicd::Event(_context, barrier); +// *event = new dclicd::Event(_context, this, CL_COMMAND_BARRIER); + } + + try { + dclasio::message::EnqueueBarrier request(_id, (event ? (*event)->remoteId() : 0), + &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued barrier (command queue ID=" << _id + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_command_queue::enqueueRead( + dclicd::Buffer *buffer, + cl_bool blocking_read, + size_t offset, + size_t cb, + void *ptr, + const std::vector& event_wait_list, + cl_event *event) { + std::shared_ptr readBuffer; + std::vector eventIds; + + if (!buffer) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + // Command queue and buffer must be associated with the same context + if (buffer->context() != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + + // Convert event wait list + createEventIdWaitList(event_wait_list, eventIds); + + // Enqueue read buffer command locally + readBuffer = std::make_shared( + CL_COMMAND_READ_BUFFER, this, cb, ptr); + enqueueCommand(readBuffer); + + // Create event + if (event) { + *event = new dclicd::Event(_context, readBuffer); + } + + // Enqueue read buffer command on command queue's compute node + try { + dclasio::message::EnqueueReadBuffer request(_id, readBuffer->remoteId(), + buffer->remoteId(), blocking_read, offset, cb, &eventIds, + (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued data download from buffer (command queue ID=" + << _id << ", buffer ID=" << buffer->remoteId() + << ", size=" << cb + << ", command ID=" << readBuffer->remoteId() + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + if (blocking_read) { + /* Wait for completion of command + * This blocking operation performs an implicit flush */ + readBuffer->wait(); + } +} + +void _cl_command_queue::enqueueWrite( + dclicd::Buffer *buffer, + cl_bool blocking_write, + size_t offset, + size_t cb, + const void *ptr, + const std::vector& event_wait_list, + cl_event *event) { + std::shared_ptr writeBuffer; + std::vector eventIds; + + if (!buffer) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + // Command queue and buffer must be associated with the same context + if (buffer->context() != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + + // Convert event wait list + createEventIdWaitList(event_wait_list, eventIds); + + // Enqueue write buffer command locally + writeBuffer = std::make_shared( + CL_COMMAND_WRITE_BUFFER, this, cb, ptr); + enqueueCommand(writeBuffer); + + // Create event + if (event) { + *event = new dclicd::Event(_context, writeBuffer, std::vector(1, buffer)); + } + + // Enqueue write buffer command on command queue's compute node + try { + dclasio::message::EnqueueWriteBuffer enqueueWriteBuffer(_id, + writeBuffer->remoteId(), buffer->remoteId(), blocking_write, + offset, cb, &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(enqueueWriteBuffer); + dcl::util::Logger << dcl::util::Info + << "Enqueued data upload to buffer (command queue ID=" << _id + << ", buffer ID=" << buffer->remoteId() + << ", size=" << cb + << ", command ID=" << writeBuffer->remoteId() + << ')' << std::endl; + } catch (const dcl::CLError& err) { + /* TODO Delete user events on other compute nodes */ + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + if (blocking_write) { + /* Wait for completion of command + * This blocking operation performs an implicit flush */ + writeBuffer->wait(); + } +} + +void _cl_command_queue::enqueueCopy( + dclicd::Buffer *src, + dclicd::Buffer *dst, + size_t src_offset, + size_t dst_offset, + size_t cb, + const std::vector& event_wait_list, + cl_event *event) { + std::vector eventIds; + + if (!src) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + if (!dst) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + // Command queue and buffer must be associated with the same context + if (src->context() != _context || dst->context() != _context) { + throw dclicd::Error(CL_INVALID_CONTEXT); + } + + // Convert event wait list + createEventIdWaitList(event_wait_list, eventIds); + + // Create event + if (event) { + std::shared_ptr copyBuffer( + std::make_shared(CL_COMMAND_COPY_BUFFER, this)); + enqueueCommand(copyBuffer); + *event = new dclicd::Event(_context, copyBuffer, std::vector(1, dst)); +// *event = new dclicd::Event(_context, this, CL_COMMAND_COPY_BUFFER); + } + + try { + dclasio::message::EnqueueCopyBuffer request(_id, (event ? (*event)->remoteId() : 0), + src->remoteId(), dst->remoteId(), src_offset, dst_offset, cb, + &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued copy buffer (command queue ID=" << _id + << ", src buffer ID=" << src->remoteId() + << ", dst buffer ID=" << dst->remoteId() + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void * _cl_command_queue::enqueueMap( + dclicd::Buffer *buffer, + cl_bool blocking_map, + cl_map_flags map_flags, + size_t offset, + size_t cb, + const std::vector& event_wait_list, + cl_event *event) { + std::shared_ptr mapBuffer; + std::vector eventIds; + void *ptr; + + if (!buffer) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + // Command queue and buffer must be associated with the same context + if (buffer->context() != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + + /* Create pointer to mapped region of buffer + * This operation allocates memory for mapping (if required) and updates the + * buffer's map count, but does not copy its data. */ + ptr = buffer->map(map_flags, offset, cb); + // FIXME Unmap memory in case of an error + + // Convert event wait list + createEventIdWaitList(event_wait_list, eventIds); + + // Enqueue map buffer command locally + mapBuffer = std::make_shared( + this, buffer, map_flags, cb, ptr); + enqueueCommand(mapBuffer); + + // Create event + if (event) { + *event = new dclicd::Event(_context, mapBuffer); + } + + try { + dclasio::message::EnqueueMapBuffer request(_id, mapBuffer->remoteId(), + buffer->remoteId(), blocking_map, map_flags, + offset, cb, + &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued map buffer (command queue ID=" << _id + << ", buffer ID=" << buffer->remoteId() + << ", command ID=" << mapBuffer->remoteId() + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + if (blocking_map) { + /* Wait for completion of command + * This blocking operation performs an implicit flush */ + mapBuffer->wait(); + } + + return ptr; +} + +void _cl_command_queue::enqueueUnmap( + cl_mem memobj, + void *mapped_ptr, + const std::vector& event_wait_list, + cl_event *event) { + std::shared_ptr unmapMemory; + std::vector eventIds; + cl_mem_object_type type; + + memobj->getInfo(CL_MEM_TYPE, sizeof(type), &type, nullptr); + + if (!memobj) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + // Command queue and memory object must be associated with the same context + if (memobj->context() != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + + // Obtain mapping data + /* TODO Generalize _cl_command_queue::enqueueUnmap for memory objects + auto mapping = memobj->findMapping(mapped_ptr); + */ + auto buffer = static_cast(memobj); + assert(buffer && "Memory object is no buffer"); + auto mapping = buffer->findMapping(mapped_ptr); + if (!mapping) { + /* mapped_ptr is not a valid pointer returned by clEnqueueMapBuffer or + * clEnqueueMapImage for this memory object */ + throw dclicd::Error(CL_INVALID_VALUE); + } + + // Convert event wait list + createEventIdWaitList(event_wait_list, eventIds); + + // Enqueue unmap memory object command locally + unmapMemory = std::make_shared( + this, buffer, mapping->flags(), mapping->cb(), mapped_ptr); + enqueueCommand(unmapMemory); + + // Create event + if (event) { + if (mapping->flags() & CL_MAP_WRITE) { + /* The memory object had been mapped for writing. Thus, the unmap + * operation modifies the memory object which is therefore + * associated with the unmap event. */ + *event = new dclicd::Event(_context, unmapMemory, std::vector(1, memobj)); + } else { + *event = new dclicd::Event(_context, unmapMemory); + } + } + + try { + switch (type) { + case CL_MEM_OBJECT_BUFFER: + { + dclasio::message::EnqueueUnmapBuffer request(_id, unmapMemory->remoteId(), + memobj->remoteId(), mapping->flags(), + mapping->offset(), mapping->cb(), + &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + break; + } + case CL_MEM_OBJECT_IMAGE2D: + case CL_MEM_OBJECT_IMAGE3D: + assert(!"clUnmapMemObject not implemented for image"); + break; + default: + throw dclicd::Error(CL_INVALID_MEM_OBJECT); + // no break + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued unmapping memory object (command queue ID=" << _id + << ", memory object ID=" << memobj->remoteId() + << ", command ID=" << unmapMemory->remoteId() + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +#if defined(CL_VERSION_1_2) +void _cl_command_queue::enqueueMigrateMemObjects( + const std::vector& mem_objects, + cl_mem_migration_flags flags, + const std::vector& event_wait_list, + cl_event *event) { + assert(!"_cl_command_queue::enqueueMigrateMemObjects not implemented"); +} +#endif // #if defined(CL_VERSION_1_2) + +void _cl_command_queue::enqueueNDRangeKernel( + cl_kernel kernel, + const std::vector& offset, + const std::vector& global, + const std::vector& local, + const std::vector& event_wait_list, + cl_event *event) { + std::vector eventIds; + + if (!kernel) throw dclicd::Error(CL_INVALID_KERNEL); + /* Command queue and kernel must be associated with the same context */ + if (kernel->program()->context() != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + + /* Convert event wait list */ + createEventIdWaitList(event_wait_list, eventIds); + + if (event) { + std::shared_ptr nDRangeKernel( + std::make_shared(CL_COMMAND_NDRANGE_KERNEL, this)); + enqueueCommand(nDRangeKernel); + *event = new dclicd::Event(_context, nDRangeKernel, kernel->writeMemoryObjects()); +// *event = new dclicd::Event(_context, this, CL_COMMAND_NDRANGE_KERNEL); + } + + /* + * Enqueue kernel (remote operation) + */ + try { + dclasio::message::EnqueueNDRangeKernel request( + _id, (event ? (*event)->remoteId() : 0), kernel->remoteId(), + offset, global, local, &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued ND range kernel (command queue ID=" << _id + << ", kernel ID=" << kernel->remoteId() + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_command_queue::enqueueTask( + cl_kernel kernel, + const std::vector& event_wait_list, + cl_event *event) { + std::vector eventIds; + + if (!kernel) throw dclicd::Error(CL_INVALID_KERNEL); + /* Command queue and kernel must be associated with the same context */ + if (kernel->program()->context() != _context) throw dclicd::Error(CL_INVALID_CONTEXT); + + /* Convert event wait list */ + createEventIdWaitList(event_wait_list, eventIds); + + if (event) { + std::shared_ptr task( + std::make_shared(CL_COMMAND_TASK, this)); + enqueueCommand(task); + *event = new dclicd::Event(_context, task, kernel->writeMemoryObjects()); +// *event = new dclicd::Event(_context, this, CL_COMMAND_TASK); + } + + /* + * Enqueue task (remote operation) + * clEnqueueTask is equivalent to calling clEnqueueNDRangeKernel with + * work_dim = 1, global_work_offset = NULL, global_work_size[0] set to 1, + * and local_work_size[0] set to 1. + */ + try { + dclasio::message::EnqueueNDRangeKernel request( + _id, (event ? (*event)->remoteId() : 0), kernel->remoteId(), + std::vector(), std::vector(1, 1), std::vector(1, 1), + &eventIds, (event != nullptr)); + _device->remote().getComputeNode().executeCommand(request); + dcl::util::Logger << dcl::util::Info + << "Enqueued task (command queue ID=" << _id + << ", kernel ID=" << kernel->remoteId() + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_command_queue::enqueueBroadcast( + std::vector commandQueueList, + dclicd::Buffer *src, + std::vector dsts, + size_t srcOffset, + const std::vector dstOffsets, + size_t cb, + const std::vector& event_wait_list, + cl_event *event) { + cl_context context; + std::map> nodeCommandQueueIds; + std::map> nodeDstIds; + std::map> nodeDstOffsets; + std::vector eventIds; + + if (!src) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + if (commandQueueList.empty() || dsts.empty()) { + throw dclicd::Error(CL_INVALID_VALUE); + } + + /* Command queues and buffers must be associated with the same context */ + context = src->context(); + + /* + * Validate command queues and source buffers + * Create ID lists + */ + assert(commandQueueList.size() == dsts.size()); + std::vector::const_iterator i = std::begin(commandQueueList); + std::vector::const_iterator j = std::begin(dsts); + std::vector::const_iterator k = std::begin(dstOffsets); + for (; i != std::end(commandQueueList) && j != std::end(dsts) && k != std::end(dstOffsets); + ++i, ++j, ++k) { + cl_command_queue queue = *i; + cl_mem dst = *j; + size_t offset = *k; + dcl::ComputeNode *computeNode; + bool inserted; + + if (!queue) throw dclicd::Error(CL_INVALID_COMMAND_QUEUE); + if (queue->_context != context) throw dclicd::Error(CL_INVALID_CONTEXT); + if (!dst) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + if (dst->context() != context) throw dclicd::Error(CL_INVALID_CONTEXT); + + /* TODO Offset of destination buffer must specify valid buffer region */ + + computeNode = &queue->computeNode(); + + nodeCommandQueueIds[computeNode].push_back(queue->remoteId()); + inserted = nodeDstIds[computeNode].insert(dst->remoteId()).second; + if (!inserted) { + /* destination buffer specified more than once */ + throw dclicd::Error(CL_INVALID_VALUE); + } + nodeDstOffsets[computeNode].push_back(offset); + } + + /* Convert event wait list */ + commandQueueList[0]->createEventIdWaitList(event_wait_list, eventIds); + +// if (event) { +// try { +// /* TODO Create broadcast command */ +// *event = new dclicd::Event(context, broadcast); +// } catch (const std::bad_alloc&) { +// throw dclicd::Error(CL_OUT_OF_RESOURCES); +// } +// } + + /* + * Enqueue broadcast (remote operation) + */ + try { + auto i = std::begin(nodeCommandQueueIds); + auto j = std::begin(nodeDstIds); + auto k = std::begin(nodeDstOffsets); + std::vector> requests; + + /* + * Create and send requests + */ + for (; i != std::end(nodeCommandQueueIds) && j != std::end(nodeDstIds); ++i, ++j) { + auto computeNode = i->first; + /* TODO Avoid copying 'enqueue broadcast buffer' requests */ + dclasio::message::EnqueueBroadcastBuffer request( + i->second, (event ? (*event)->remoteId() : 0), + src->remoteId(), + std::vector(std::begin(j->second), std::end(j->second)), + srcOffset, k->second, cb, + &eventIds, (event != nullptr)); + computeNode->sendRequest(request); + + requests.push_back(std::make_pair(computeNode, request)); // save pending request + } + + /* + * Await responses from all compute nodes + */ + for (auto request : requests) { + request.first->awaitResponse(request.second); + /* TODO Receive responses from *all* compute nodes, i.e. do not stop receipt on first failure */ + } + + dcl::util::Logger << dcl::util::Info + << "Enqueued broadcast buffer (src buffer ID=" << src->remoteId() + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_command_queue::enqueueReduce( + std::vector srcs, + dclicd::Buffer *dst, +// const std::vector srcOffsets, +// size_t dstOffset, +// size_t cb, + cl_kernel kernel, + const std::vector& offset, + const std::vector& global, + const std::vector& local, +// cl_reduce_operator_WWU oper, + const std::vector& event_wait_list, + cl_event *event) { + cl_context context; + std::vector srcIds; + std::vector eventIds; + + if (!dst) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + + /* Command queues, buffers, and kernel must be associated with the same context */ + context = dst->context(); + + /* + * Validate source buffers + * Create ID lists + */ + for (auto src : srcs) { + if (!src) throw dclicd::Error(CL_INVALID_MEM_OBJECT); + if (src->context() != context) throw dclicd::Error(CL_INVALID_CONTEXT); + + srcIds.push_back(src->remoteId()); + } + + /* + * Validate kernel + */ + if (kernel->program()->context() != context) throw dclicd::Error(CL_INVALID_CONTEXT); + + /* Convert event wait list */ + createEventIdWaitList(event_wait_list, eventIds); + +// if (event) { +// try { +// /* TODO Create reduce command */ +// *event = new dclicd::Event(context, *reduce); +// } catch (const std::bad_alloc&) { +// throw dclicd::Error(CL_OUT_OF_RESOURCES); +// } +// } + + /* + * Enqueue reduction (remote operation) + */ + try { + dclasio::message::EnqueueReduceBuffer request( + _id, (event ? (*event)->remoteId() : 0), + srcIds, dst->remoteId(), + kernel->remoteId(), offset, global, local, + &eventIds, (event != nullptr)); + executeCommand(context->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Enqueued reduce buffer (dst buffer ID=" << dst->remoteId() + << ", command ID=" << (event ? (*event)->remoteId() : 0) + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} diff --git a/icdpp/src/CommandQueue.h b/icdpp/src/CommandQueue.h new file mode 100644 index 0000000..b968471 --- /dev/null +++ b/icdpp/src/CommandQueue.h @@ -0,0 +1,278 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file CommandQueue.h + * + * @date 2011-05-31 + * @author Karsten Jeschkies + */ + +#ifndef CL_COMMANDQUEUE_H_ +#define CL_COMMANDQUEUE_H_ + +#include "Context.h" +#include "Device.h" +#include "Retainable.h" + +#include "dclicd/command/Command.h" + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dclicd { + +/* forward declarations */ +class Buffer; +class ReadMemoryEvent; + +} /* namespace dclicd */ + +/******************************************************************************/ + +class _cl_command_queue: +public _cl_retainable, +public dcl::Remote, +public dcl::CommandQueueListener { +public: + static void enqueueBroadcast( + std::vector commandQueueList, + dclicd::Buffer * src, + std::vector dsts, + size_t srcOffset, + const std::vector dstOffsets, + size_t cb, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + void enqueueReduce( + std::vector srcs, + dclicd::Buffer * dst, +// const std::vector srcOffsets, +// size_t dstOffset, +// size_t cb, + cl_kernel kernel, + const std::vector& global_work_offset, + const std::vector& global_work_size, + const std::vector& local_work_size, +// cl_reduce_operator_WWU oper, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + + _cl_command_queue( + cl_context context, + cl_device_id device, + cl_command_queue_properties properties); + virtual ~_cl_command_queue(); + + dcl::ComputeNode& computeNode() const; + + void getInfo( + cl_command_queue_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + void finish(); + void flush(); + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + void enqueueWaitForEvents( + const std::vector& eventList); +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + + /** + * @brief Enqueues a marker command which waits for either a list of events + * to complete, or all previously enqueued commands to complete. + * + * This methods implements the OpenCL 1.2 clEnqueueMarkerWithWaitList API. + * It is also used to implement the deprecated clEnqueueMarker API. + * + * @param[in] event_wait_list + * @param[in] event + */ + void enqueueMarker( + const std::vector& event_wait_list, + cl_event * event); + + /** + * @brief A synchronization point that enqueues a barrier operation. + * + * This methods implements the OpenCL 1.2 clEnqueueBarrierWithWaitList API. + * It is also used to implement the deprecated clEnqueueBarrier API. + * + * @param[in] event_wait_list + * @param[in] event + */ + void enqueueBarrier( + const std::vector& event_wait_list, + cl_event *event = nullptr); + + void enqueueWrite( + dclicd::Buffer * buffer, + cl_bool blocking_write, + size_t offset, + size_t cb, + const void * ptr, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + void enqueueRead( + dclicd::Buffer * buffer, + cl_bool blocking_read, + size_t offset, + size_t cb, + void * ptr, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + void enqueueCopy( + dclicd::Buffer * src, + dclicd::Buffer * dst, + size_t srcOffset, + size_t dstOffset, + size_t cb, + const std::vector& eventWaitList, + cl_event *event = nullptr); + + void * enqueueMap( + dclicd::Buffer * buffer, + cl_bool blocking_map, + cl_map_flags map_flags, + size_t offset, + size_t cb, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + void enqueueUnmap( + cl_mem memobj, + void * mapped_ptr, + const std::vector& event_wait_list, + cl_event *event = nullptr); + +#if defined(CL_VERSION_1_2) + void enqueueMigrateMemObjects( + const std::vector& mem_objects, + cl_mem_migration_flags flags, + const std::vector& event_wait_list, + cl_event *event = nullptr); +#endif // #if defined(CL_VERSION_1_2) + + void enqueueNDRangeKernel( + cl_kernel kernel, + const std::vector& global_work_offset, + const std::vector& global_work_size, + const std::vector& local_work_size, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + void enqueueTask( + cl_kernel kernel, + const std::vector& event_wait_list, + cl_event *event = nullptr); + + /* + * Command queue listener APIs + */ + + void onFinish(); + +protected: + void destroy(); + +private: + void createEventIdWaitList( + const std::vector& event_wait_list, + std::vector& eventIds); + + /** + * @brief Enqueues a command. + * + * Add a command to this command queue's command list. + * Besides, completed command are removed from the command list. + * + * @param[in] command the command to enqueue + */ + void enqueueCommand( + const std::shared_ptr& command); + + /** + * @brief Finishes this command queue locally. + * + * Unlike finish, which ensures that *all* commands queued to this command + * queue have finished, this method only ensures that all commands managed + * by this command queue, i.e., on the host, have finished. + * + * This is a blocking operation. + */ + void finishLocally(); + + cl_context _context; + cl_device_id _device; + cl_command_queue_properties _properties; + /** + * @brief A list of enqueued commands + * + * This list stored enqueued command which are listening to remote command. + * Completed events are removed from this list when a new command is + * enqueued or when the command queue is finished. + * + * This list ensures that command are not deleted before they have been + * finished *and* have deleted their associated event. + * + * @see enqueueCommand + * @see command::Command::onExecutionStatusChanged + */ + std::vector> _commands; + std::mutex _commandsMutex; +}; + +#endif /* CL_COMMANDQUEUE_H_ */ diff --git a/icdpp/src/ComputeNode.cpp b/icdpp/src/ComputeNode.cpp new file mode 100644 index 0000000..cd3e264 --- /dev/null +++ b/icdpp/src/ComputeNode.cpp @@ -0,0 +1,187 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file ComputeNode.cpp + * + * @date 2011-04-06 + * @author Philipp Kegel + */ + +#include "ComputeNode.h" + +#include "Device.h" +#include "Platform.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include + + +_cl_compute_node_WWU::_cl_compute_node_WWU( + cl_platform_id platform, + dcl::ComputeNode& remote, + void (*pfn_notify)( + cl_compute_node_WWU, cl_int, void *), + void *user_data) : + _platform(platform), _pfnNotify(pfn_notify), _userData(user_data), + _remote(remote) +{ + assert(platform != nullptr); + assert(pfn_notify == nullptr && "Compute node callback not implemented"); + + if (user_data != nullptr && pfn_notify == nullptr) { + throw dclicd::Error(CL_INVALID_VALUE); + } + + initDeviceList(); +} + +_cl_compute_node_WWU::~_cl_compute_node_WWU() { +} + +void _cl_compute_node_WWU::destroy() { + assert(_ref_count == 0); + /* TODO Avoid 'delete this' in _cl_compute_node_WWU::destroy */ + _platform->destroyComputeNode(this); +} + +void _cl_compute_node_WWU::getDevices( + cl_device_type type, + std::vector& devices) const { + switch (type) { + case CL_DEVICE_TYPE_DEFAULT: + case CL_DEVICE_TYPE_CPU: + case CL_DEVICE_TYPE_GPU: + case CL_DEVICE_TYPE_ACCELERATOR: +#if defined(CL_VERSION_1_2) + case CL_DEVICE_TYPE_CUSTOM: +#endif // #if defined(CL_VERSION_1_2) + /* device type is valid; return all devices of specified type */ + devices.clear(); // clear output list + + for (const auto& device : _devices) { + cl_device_type deviceType; + + device->getInfo(CL_DEVICE_TYPE, sizeof(cl_device_type), &deviceType, nullptr); + if ((deviceType & type)) { + devices.push_back(device.get()); + } + } + + break; + case CL_DEVICE_TYPE_ALL: + devices.clear(); // clear output list + /* just return all devices */ + for (const auto& device : _devices) { + devices.push_back(device.get()); + } + break; + default: + throw dclicd::Error(CL_INVALID_DEVICE_TYPE); + } + + if (devices.empty()) { + throw dclicd::Error(CL_DEVICE_NOT_FOUND); + } +} + +void _cl_compute_node_WWU::getInfo( + cl_compute_node_info_WWU param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_NODE_AVAILABLE_WWU: + /* TODO Return availability status of compute node + * Compute nodes become unavailable if they loose connection (and so do + * their devices). */ + assert(!"_cl_compute_node_WWU::getInfo not fully implemented yet"); + break; + case CL_NODE_PLATFORM_WWU: + dclicd::copy_info(_platform, param_value_size, param_value, + param_value_size_ret); + break; + case CL_NODE_REFERENCE_COUNT_WWU: + dclicd::copy_info(_ref_count, param_value_size, param_value, + param_value_size_ret); + break; + case CL_NODE_URL_WWU: + dclicd::copy_info(_remote.url(), param_value_size, param_value, + param_value_size_ret); + break; + /* TODO Return platform info of compute node's platform */ + case CL_NODE_PROFILE_WWU: + case CL_NODE_VERSION_WWU: + case CL_NODE_NAME_WWU: + case CL_NODE_VENDOR_WWU: + case CL_NODE_EXTENSIONS_WWU: + assert(!"_cl_compute_node_WWU::getInfo not fully implemented yet"); + break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +dcl::ComputeNode& _cl_compute_node_WWU::remote() const { + return _remote; +} + +void _cl_compute_node_WWU::initDeviceList() { + std::vector devices; + + _remote.getDevices(devices); + + _devices.clear(); + for (auto device : devices) { + _devices.push_back(std::unique_ptr<_cl_device_id>( + new _cl_device_id(this, *device))); + } +} diff --git a/icdpp/src/ComputeNode.h b/icdpp/src/ComputeNode.h new file mode 100644 index 0000000..139612e --- /dev/null +++ b/icdpp/src/ComputeNode.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file ComputeNode.h + * + * @date 2011-04-06 + * @author Philipp Kegel + */ + +#ifndef CL_COMPUTENODE_H_ +#define CL_COMPUTENODE_H_ + +#include "Platform.h" +#include "Retainable.h" + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include + + +class _cl_compute_node_WWU : + public _cl_retainable { + friend class _cl_platform_id; + +public: + void getDevices( + cl_device_type, + std::vector&) const; + void getInfo( + cl_compute_node_info_WWU param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + /** + * @brief Returns a reference to the remote compute node instance. + */ + /* TODO Hide method _cl_compute_node_id_WWU::remote to not break API design */ + dcl::ComputeNode& remote() const; + +protected: + void destroy(); + +private: + /** + * @brief Create a compute node. + * + * This method must not be called directly. + * Use \code ComputeNodeManager::createComputeNode instead. + * + * @param[in] platform + * @param[in] remote the remote compute node instance + * @param[in] pfn_notify A callback function that can be registered by the application. + * This callback function will be used by the OpenCL implementation to report information on errors that occur during communication with this compute node. + * This callback function may be called asynchronously by the OpenCL implementation. + * It is the application's responsibility to ensure that the callback function is thread-safe. + * If pfn_notify is NULL, no callback function is registered. + * @param[in] user_data + * + * @see ComputeNodeManager::createComputeNode + */ + _cl_compute_node_WWU( + cl_platform_id platform, + dcl::ComputeNode& remote, + void (* pfn_notify)( + cl_compute_node_WWU compute_node, + cl_int errcode, + void * user_data) = nullptr, + void *user_data = nullptr); + virtual ~_cl_compute_node_WWU(); + + /* Compute nodes must be non-copyable */ + _cl_compute_node_WWU( + const _cl_compute_node_WWU&) = delete; + _cl_compute_node_WWU& operator=( + const _cl_compute_node_WWU&) = delete; + + /** + * @brief Initializes this compute node's device list. + * + * Queries valid devices from the compute node proxies and creates + * application level device objects for each proxy. + * + * This method must only be called once. + */ + void initDeviceList(); + + cl_platform_id _platform; + void (*_pfnNotify)( + cl_compute_node_WWU compute_node, + cl_int errcode, + void * user_data); + void *_userData; + std::vector> _devices; + + dcl::ComputeNode& _remote; /**< remote compute node instance */ +}; + +#endif /* CL_COMPUTENODE_H_ */ diff --git a/icdpp/src/Context.cpp b/icdpp/src/Context.cpp new file mode 100644 index 0000000..dfbb821 --- /dev/null +++ b/icdpp/src/Context.cpp @@ -0,0 +1,363 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Context.cpp + * + * \date 2011-04-06 + * \author Philipp Kegel + */ + +#include "Context.h" + +#include "ComputeNode.h" +#include "Device.h" +#include "Platform.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include "dclicd/detail/ContextProperties.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +void _cl_context::init( + const std::vector& devices) { + std::map> computeNodeDeviceIds; + + assert(!devices.empty()); // device list must not be empty + + /* + * Obtain compute nodes' lists of device IDs + */ + for (auto device : devices) { + if (!device) throw dclicd::Error(CL_INVALID_DEVICE); + /* Availability of device is checked by the compute node's OpenCL implementation */ + + computeNodeDeviceIds[&(device->remote().getComputeNode())].push_back(device->remote().getId()); + } + + try { + std::vector computeNodeIds; + std::vector> requests; + + /* + * TODO Create list of compute node IDs + computeNodeIds.reserve(computeNodeDeviceIds.size()); + for (auto deviceIds : computeNodeDeviceIds) { + computeNodeIds.push_back(deviceIds.first->getId()); + } + */ + + /* + * Create and send requests + */ + for (auto deviceIds : computeNodeDeviceIds) { + dcl::ComputeNode *computeNode = deviceIds.first; + /* TODO Add context properties to request + * However, the platform (dOpenCL) must be stripped from the + * transmitted properties because it is not portable and should be + * replaced by the native platform selected on the compute node. */ + /* TODO Avoid copying 'create context' requests */ + dclasio::message::CreateContext request(_id, computeNodeIds, deviceIds.second); + computeNode->sendRequest(request); + + requests.push_back(std::make_pair(computeNode, request)); // save pending request + } + + /* + * Await responses from all compute nodes + */ + for (auto request : requests) { + dcl::ComputeNode *computeNode = request.first; + computeNode->awaitResponse(request.second); + _computeNodes.push_back(computeNode); // update compute node list + + /* TODO Receive responses from *all* compute nodes, i.e., do not stop receipt on first failure */ + } + + /* Register context as context listener */ + getPlatform()->remote().objectRegistry().bind(_id, *this); + + dcl::util::Logger << dcl::util::Info + << "Context created (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + _devices = devices; +} + +cl_platform_id _cl_context::getPlatform() const { + cl_platform_id platform; + + /* + * Select platform + */ + if (_properties) { + platform = _properties->property(); + } else { + /* Behavior is implementation defined, if properties is NULL */ + platform = _cl_platform_id::dOpenCL(); + } + + return platform; +} + +_cl_context::_cl_context( + const dclicd::detail::ContextProperties *properties, + const std::vector& devices, + void (*pfn_notify)( + const char *errinfo, + const void *private_info, + size_t cb, + void *user_data), + void *user_data) : + _properties(properties ? new dclicd::detail::ContextProperties(*properties) : nullptr), + _pfnNotify(pfn_notify), _userData(user_data) +{ + if (devices.empty()) throw dclicd::Error(CL_INVALID_VALUE); + if (pfn_notify == nullptr && user_data != nullptr) throw dclicd::Error(CL_INVALID_VALUE); + + /* Ensure that device are from platform dOpenCL */ + for (auto device : devices) { + cl_platform_id devicePlatform; + + device->getInfo(CL_DEVICE_PLATFORM, sizeof(devicePlatform), &devicePlatform, nullptr); + if (devicePlatform != getPlatform()) throw dclicd::Error(CL_INVALID_DEVICE); + } + + init(devices); +} + +_cl_context::_cl_context( + const dclicd::detail::ContextProperties *properties, + cl_device_type device_type, + void (*pfn_notify)( + const char *errinfo, + const void *private_info, + size_t cb, + void *user_data), + void *user_data) : + _properties(properties ? new dclicd::detail::ContextProperties(*properties) : nullptr), + _pfnNotify(pfn_notify), _userData(user_data) +{ + std::vector devices; + + if (pfn_notify == nullptr && user_data != nullptr) throw dclicd::Error(CL_INVALID_VALUE); + + /* obtain device list */ + getPlatform()->getDevices(device_type, devices); + + init(devices); +} + +_cl_context::_cl_context( + const dclicd::detail::ContextProperties *properties, + const std::vector& computeNodes, + void (*pfn_notify)( + const char *errinfo, + const void *private_info, + size_t cb, + void *user_data), + void *user_data) : + _properties(properties ? new dclicd::detail::ContextProperties(*properties) : nullptr), + _pfnNotify(pfn_notify), _userData(user_data) +{ + std::vector devices; + + if (computeNodes.empty()) { throw dclicd::Error(CL_INVALID_VALUE); } + if (pfn_notify == nullptr && user_data != nullptr) { throw dclicd::Error(CL_INVALID_VALUE); } + + /* obtain device list */ + for (auto computeNode : computeNodes) { + cl_platform_id nodePlatform; + + /* Ensure that compute node is associated with selected platform */ + computeNode->getInfo(CL_NODE_PLATFORM_WWU, sizeof(nodePlatform), &nodePlatform, nullptr); + if (nodePlatform != getPlatform()) throw dclicd::Error(CL_INVALID_NODE_WWU); + + try { + std::vector nodeDevices; + + computeNode->getDevices(CL_DEVICE_TYPE_ALL, nodeDevices); + devices.insert(std::end(devices), std::begin(nodeDevices), std::end(nodeDevices)); + } catch (dclicd::Error& err) { + if (err.err() == CL_DEVICE_NOT_FOUND) { + continue; // ignore CL_DEVICE_NOT_FOUND + } + + throw; // rethrow error + } + } + + if (devices.empty()) throw dclicd::Error(CL_DEVICE_NOT_FOUND); + + init(devices); +} + +_cl_context::~_cl_context() { +} + +void _cl_context::destroy() { + assert(_ref_count == 0); + + try { + dclasio::message::DeleteContext deleteContext(_id); + dcl::executeCommand(_computeNodes, deleteContext); + + /* Remove this context from list of context listeners */ + getPlatform()->remote().objectRegistry().unbind(_id); + + dcl::util::Logger << dcl::util::Info + << "Context deleted (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +const std::vector& _cl_context::computeNodes() const { + return _computeNodes; +} + +const std::vector& _cl_context::devices() const { + return _devices; +} + +void _cl_context::getInfo( + cl_context_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_CONTEXT_REFERENCE_COUNT: + dclicd::copy_info(_ref_count, param_value_size, + param_value, param_value_size_ret); + break; + case CL_CONTEXT_NUM_DEVICES: + dclicd::copy_info(static_cast(_devices.size()), + param_value_size, param_value, param_value_size_ret); + break; + case CL_CONTEXT_DEVICES: + /* deep copy device list */ + dclicd::copy_info(_devices, param_value_size, param_value, + param_value_size_ret); + break; + case CL_CONTEXT_PROPERTIES: + if (_properties) { + /* deep copy properties list */ + dclicd::copy_info( + _properties->size() * sizeof(cl_context_properties), _properties->data(), + param_value_size, param_value, param_value_size_ret); + } else { + dclicd::copy_info(0, nullptr, param_value_size, param_value, param_value_size_ret); + } + break; +// case CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR: +// assert(!"cl_khr_d3d10_sharing not supported by dOpenCL"); +// break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +void _cl_context::getSupportedImageFormats( + cl_mem_flags flags, + cl_mem_object_type image_type, + std::vector& imageFormats) const { + /* TODO Implement _cl_context::getSupportedImageFormats */ +// assert(!"_cl_context::getSupportedImageFormats not implemented yet"); + /* Do nothing in order to return an empty list */ + imageFormats.clear(); +} + +bool _cl_context::hasDevice(cl_device_id device) const { + return (std::find(std::begin(_devices), std::end(_devices), device) != std::end(_devices)); +} + +/* + * Context listener APIs + */ + +void _cl_context::onError(const char *errorInfo, + const void *private_info, size_t cb) { + if (_pfnNotify) { + _pfnNotify(errorInfo, private_info, cb, _userData); + } +} diff --git a/icdpp/src/Context.h b/icdpp/src/Context.h new file mode 100644 index 0000000..5577c52 --- /dev/null +++ b/icdpp/src/Context.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Context.h + * + * \date 2011-04-06 + * \author Philipp Kegel + */ + +#ifndef CL_CONTEXT_H_ +#define CL_CONTEXT_H_ + +#include "Retainable.h" + +#include "dclicd/detail/ContextProperties.h" + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include + + +class _cl_context: +public _cl_retainable, +public dcl::Remote, +public dcl::ContextListener { +public: + /*! + * \brief Creates an OpenCL context. + * + * \param[in] properties context properties; may be NULL + * \param[in] devices a list of unique devices returned by \c Platform::getDevices. + * Duplicate devices specified in \c devices are ignored. + * \param[in] pfn_notify a callback function that can be registered by the application + * \param[in] user_data passed as the \c user_data argument when \c pfn_notify is called. + * user_data can be \c NULL. + */ + _cl_context( + const dclicd::detail::ContextProperties * properties, + const std::vector& devices, + void (* pfn_notify) ( + const char * errinfo, + const void * private_info, + size_t cb, + void * user_data), + void * user_data); + + /*! + * \brief Creates an OpenCL context from a device type that identifies the specific device(s) to use. + * + * \param[in] properties context properties; may be NULL + * \param[in] device_type a bit-field that identifies the type of device + * \param[in] pfn_notify a callback function that can be registered by the application + * \param[in] user_data passed as the \c user_data argument when \c pfn_notify is called. + * \c user_data can be \c NULL. + */ + _cl_context( + const dclicd::detail::ContextProperties * properties, + cl_device_type device_type, + void (* pfn_notify)( + const char * errinfo, + const void * private_info, + size_t cb, + void * user_data), + void * user_data); + + /*! + * \brief Creates an OpenCL context from all devices of the specified compute nodes. + * + * \param[in] properties context properties; may be NULL + * \param[in] compute_nodes a list of compute nodes + * \param[in] pfn_notify a callback function that can be registered by the application + * \param[in] user_data passed as the \c user_data argument when \c pfn_notify is called. + * \c user_data can be \c NULL. + */ + _cl_context( + const dclicd::detail::ContextProperties * properties, + const std::vector& computeNodes, + void (* pfn_notify)( + const char * errinfo, + const void * private_info, + size_t cb, + void * user_data), + void * user_data); + + virtual ~_cl_context(); + + const std::vector& computeNodes() const; + + /*! + * \brief Returns the platform associated with context. + * + * This platform either has been specified in context properties, or is a + * default platform that has been selected by the implementation. + * + * \return a platform + */ + cl_platform_id getPlatform() const; + + /*! + * \brief Returns the devices associated with this context. + * + * This method is an efficient and convenient alternative for getInfo. + * + * \return a list of devices + */ + const std::vector& devices() const; + void getInfo( + cl_context_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + void getSupportedImageFormats( + cl_mem_flags flags, + cl_mem_object_type image_type, + std::vector& imageFormats) const; + + bool hasDevice( + cl_device_id device) const; + + /* + * Context listener APIs + */ + void onError( + const char *errorInfo, + const void *private_info, + size_t cb); + +protected: + void destroy(); + +private: + /*! + * \brief Initializes a newly created context from a list of devices. + * + * \param[in] devices a list of devices that will associated with the context + */ + void init( + const std::vector&); + + std::vector _computeNodes; //!< compute nodes hosting this context + + std::unique_ptr _properties; + std::vector _devices; + void (*_pfnNotify)( + const char *errinfo, + const void *private_info, + size_t cb, + void *user_data); + void *_userData; +}; + +#endif /* CL_CONTEXT_H_ */ diff --git a/icdpp/src/Device.cpp b/icdpp/src/Device.cpp new file mode 100644 index 0000000..4e1a041 --- /dev/null +++ b/icdpp/src/Device.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Device.cpp + * + * \date 2011-04-06 + * \author Philipp Kegel + */ + +#include "Device.h" + +#include "ComputeNode.h" +#include "Platform.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + + +_cl_device_id::_cl_device_id( + cl_compute_node_WWU computeNode, + dcl::Device& device) : + _computeNode(computeNode), _device(device) { + /* TODO Increase reference count of associated compute node */ +} + +_cl_device_id::~_cl_device_id() { + /* TODO Decrease reference count of associated compute node */ +} + +void _cl_device_id::getInfo( + cl_device_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_DEVICE_COMPUTE_NODE_WWU: + dclicd::copy_info(_computeNode, param_value_size, param_value, + param_value_size_ret); + break; + case CL_DEVICE_PLATFORM: + _computeNode->getInfo(CL_NODE_PLATFORM_WWU, param_value_size, + param_value, param_value_size_ret); + break; + case CL_DEVICE_EXECUTION_CAPABILITIES: + /* Devices must not report CL_EXEC_NATIVE_KERNEL capability as native + * kernels cannot be executed by remote devices. */ + /* TODO Unset CL_EXEC_NATIVE_KERNEL in value returned by remote device */ + dclicd::copy_info(CL_EXEC_KERNEL, + param_value_size, param_value, param_value_size_ret); + break; + case CL_DEVICE_AVAILABLE: + /* Device available is a transient property and thus cannot be cached */ + /* TODO Return false (device unavailable) if its compute node is not connected */ + try { + dcl::Binary param; + + _device.getInfo(param_name, param); + + dclicd::copy_info(param, param_value_size, + param_value, param_value_size_ret); + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + break; + default: + { + std::lock_guard lock(_infoCacheMutex); + + auto i = _infoCache.find(param_name); // search device info in cache + if (i == std::end(_infoCache)) { + std::pair entry; + + /* + * Cache miss: query device info from compute node + */ + try { + entry.first = param_name; + _device.getInfo(param_name, entry.second); + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + switch (param_name) { + case CL_DEVICE_EXTENSIONS: + /* TODO Devices must not report support for CL/GL or CL/DirectX interop */ + break; + } + + i = _infoCache.insert(std::move(entry)).first; + } + + dclicd::copy_info(i->second, param_value_size, + param_value, param_value_size_ret); + } + /* no break */ + } +} + +dcl::Device& _cl_device_id::remote() const { + return _device; +} diff --git a/icdpp/src/Device.h b/icdpp/src/Device.h new file mode 100644 index 0000000..64323a9 --- /dev/null +++ b/icdpp/src/Device.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Device.h + * + * \date 2011-04-06 + * \author Philipp Kegel + */ + +#ifndef CL_DEVICE_H_ +#define CL_DEVICE_H_ + +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include + + +class _cl_device_id { +public: + _cl_device_id( + cl_compute_node_WWU computeNode, + dcl::Device& device); + virtual ~_cl_device_id(); + + void getInfo( + cl_device_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + /*! + * \brief Returns a reference to the remote device instance. + */ + dcl::Device& remote() const; + +private: + cl_compute_node_WWU _computeNode; + + mutable std::map _infoCache; + mutable std::mutex _infoCacheMutex; + + dcl::Device& _device; +}; + +#endif /* CL_DEVICE_H_ */ diff --git a/icdpp/src/Event.cpp b/icdpp/src/Event.cpp new file mode 100644 index 0000000..e0889bb --- /dev/null +++ b/icdpp/src/Event.cpp @@ -0,0 +1,307 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.cpp + * + * \date 2011-06-21 + * \author Philipp Kegel + * \author Louay Hashim + */ + +#include "Event.h" + +#include "Context.h" +#include "CommandQueue.h" +#include "Retainable.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include + +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +_cl_event::_cl_event(cl_context context, cl_int status) : + _context(context), _status(status) { + if (!context) { throw dclicd::Error(CL_INVALID_CONTEXT); } +} + +_cl_event::~_cl_event() { } + +void _cl_event::retain() { + std::lock_guard lock(_statusMutex); + ++_ref_count; +} + +bool _cl_event::release() { + std::lock_guard lock(_statusMutex); + cl_uint refCount; + + refCount = _ref_count--; + assert(refCount > 0); // _ref_count must be greater than zero when calling release + + if (refCount == 1 && isComplete()) { + destroy(); + return true; + } else { + return false; + } +} + +void _cl_event::destroy() { + /* Events must only be deleted if their reference count is 0 *and* their + * associated command is completed (or terminated). + * The event is required to forward its execution status to remote events. + * + * Note that the event on the host does not have to be retained for + * enqueued commands that require a wait for this event as the remote + * events are implicitly retained by the compute nodes' OpenCL + * implementations. */ + assert(_ref_count == 0); + assert(isComplete()); + + try { + dclasio::message::DeleteEvent request(remoteId()); + dcl::executeCommand(_context->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Event deleted (ID=" << remoteId() << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_event::waitForEvents(const std::vector& event_list) { + cl_event event; + cl_context context; + cl_command_queue queue; + std::set queues; + + if (event_list.empty()) throw dclicd::Error(CL_INVALID_VALUE); + + /* + * Validate first event in list + */ + event = event_list.front(); + if (!event) throw dclicd::Error(CL_INVALID_EVENT); + + context = event->_context; + + queue = event->commandQueue(); + if (queue) { + queues.insert(queue); + } + + /* + * Validate remaining events + */ + for (auto event : event_list) { + if (!event) throw dclicd::Error(CL_INVALID_EVENT); + if (event->_context != context) throw dclicd::Error(CL_INVALID_CONTEXT); + + queue = event->commandQueue(); + if (queue) { + queues.insert(queue); + } + } + + /* Flush command queues */ + for (auto queue : queues) { + queue->flush(); + } + + /* + * Wait for events + */ + try { + /* Here, @c waitNoFlush is used to avoid redundant flushing of command queues. */ + for (auto event : event_list) { + event->waitNoFlush(); + } + } catch (const dclicd::Error&) { + /* the execution status of any of the events in event_list is a negative + * integer value */ + throw dclicd::Error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); + } +} + +void _cl_event::setCallback( + cl_int command_exec_callback_type, + void (CL_CALLBACK *pfn_event_notify)( + cl_event event, + cl_int event_command_exec_status, + void *user_data), + void *user_data) { + if (command_exec_callback_type != CL_COMPLETE) throw dclicd::Error(CL_INVALID_VALUE); + if (!pfn_event_notify) throw dclicd::Error(CL_INVALID_VALUE); + + { + std::lock_guard lock(_statusMutex); + + /* + * The following mechanism is the reason an event requires its own + * command execution status rather than querying it from its associated + * command. + * When a callback is set, it must be called immediately if the event's + * command execution status already is equal to (or lower than) the + * callback's command execution status. However, this status must not + * change between adding the callback to the list and checking if the + * callback should be triggered immediately. + * Therefore, adding the callback and checking the event's command + * execution status must be performed atomically. + */ + if (_status <= command_exec_callback_type) { + pfn_event_notify(this, CL_COMPLETE, user_data); + } + + /* Add callback to list */ + _callbacks[command_exec_callback_type].push_back( + std::make_pair(pfn_event_notify, user_data)); + } +} + +void _cl_event::getInfo( + cl_event_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_EVENT_COMMAND_QUEUE: + dclicd::copy_info(commandQueue(), param_value_size, + param_value, param_value_size_ret); + break; + case CL_EVENT_CONTEXT: + dclicd::copy_info(_context, param_value_size, + param_value, param_value_size_ret); + break; + case CL_EVENT_COMMAND_EXECUTION_STATUS: + { + std::lock_guard lock(_statusMutex); + dclicd::copy_info(_status, param_value_size, + param_value, param_value_size_ret); + break; + } + case CL_EVENT_REFERENCE_COUNT: + { + dclicd::copy_info(_ref_count, param_value_size, + param_value, param_value_size_ret); + break; + } + case CL_EVENT_COMMAND_TYPE: + dclicd::copy_info(commandType(), param_value_size, + param_value, param_value_size_ret); + break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +bool _cl_event::isComplete() const { + return (_status < 0 /* terminated */ + || _status == CL_COMPLETE); +} + +void _cl_event::waitNoFlush() const { + std::lock_guard lock(_statusMutex); + while (_status > CL_COMPLETE) _statusChanged.wait(_statusMutex); +} + +bool _cl_event::setCommandExecutionStatus(cl_int status) { + std::lock_guard lock(_statusMutex); + + /* Trigger callback's *before* setting the event complete. Otherwise, an + * application thread waiting for the event to complete may be resumed and + * then releases *and* deletes the event concurrently. + * + * In order to allow callbacks to call methods of the event, the event's + * lock has to be reentrant. */ + triggerCallbacks(status); + + _status = status; + _statusChanged.notify_all(); + + if (_ref_count == 0 && isComplete()) { + destroy(); + return true; + } else { + return false; + } +} + +void _cl_event::triggerCallbacks(cl_int status) { + /* FIXME Event callbacks should be able to release their event + * Though, an event must not be deleted (by the implementation) before all + * callbacks have been called, as the event is passed as an argument. */ + + /* + * Call callback functions registered for CL_COMPLETE if the event's + * command has completed successfully or is abnormally terminated (i.e., + * status < 0). + */ + auto i = _callbacks.find((status <= CL_COMPLETE) ? CL_COMPLETE : status); + if (i != std::end(_callbacks)) { + for (auto callback : i->second) { + callback.first(this, status, callback.second); + } + } +} diff --git a/icdpp/src/Event.h b/icdpp/src/Event.h new file mode 100644 index 0000000..3f60926 --- /dev/null +++ b/icdpp/src/Event.h @@ -0,0 +1,207 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.h + * + * \date 2011-06-21 + * \author Philipp Kegel + * \author Louay Hashim + */ + +#ifndef CL_EVENT_H_ +#define CL_EVENT_H_ + +#include "Retainable.h" + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + + +class _cl_event: +public _cl_retainable { +public: + /*! + * \brief Waits until all events in event_list are complete. + * This method implements clWaitForEvents. + * As by the OpenCL specification this is a blocking operation and thus + * implicitly calls _cl_command_queue::flush on the events' command + * queues. + * + * \param[in] event_list the events to wait for + */ + static void waitForEvents( + const std::vector& event_list); + + + virtual ~_cl_event(); + + void retain(); + bool release(); + + virtual dcl::object_id remoteId() const = 0; + + /** + * \brief Wait for the event to be completed. + * + * This method is a convenience method for waitForEvents. + */ + virtual void wait() const = 0; + + void setCallback( + cl_int command_exec_callback_type, + void (CL_CALLBACK * pfn_event_notify)( + cl_event event, + cl_int event_command_exec_status, + void *user_data), + void * user_data); + + void getInfo( + cl_event_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + /*! + * \brief Returns profiling information on this event. + * + * \param[in] param_name + * \param[in] param_size + * \param[out] param_value + * \param[out] param_size_ret + */ + virtual void getProfilingInfo( + cl_profiling_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const = 0; + +protected: + /*! + * \brief Creates a (user) event. + * + * \param[in] context + * \param[in] status initial event status + */ + _cl_event( + cl_context context, + cl_int status); + + /*! + * \brief Query command type. + * + * This method is reserved for internal use by getInfo. + * + * \return the type of the command that is associated with this event + */ + virtual cl_command_type commandType() const = 0; + + /*! + * \brief Query the command queue associated with this event. + * + * This method is reserved for internal use by getInfo. + * + * \return the command queue associated with this event + */ + virtual cl_command_queue commandQueue() const = 0; + + /*! + * \brief Checks, if this event is complete + * + * This method is reserved for internal use. + * + * \return true, if this event is complete, otherwise false + */ + bool isComplete() const; + + /*! + * \brief Waits for the event to be completed. + * + * This method is reserved for internal use. + * Unlike \c wait it does *not* perform an implicit flush. + */ + void waitNoFlush() const; + + /*! + * \brief Sets the event's command execution status. + * + * This event is destroyed, if its reference count is zero and its + * associated command has finished. The caller is responsible for deleting + * this event. + * + * This method is reserved for internal use. + * + * \param[in] status the command execution status this events should switch to + * \return \c true, if this event has been destroyed, otherwise \c false + */ + bool setCommandExecutionStatus( + cl_int status); + + void destroy(); + + cl_context _context; + + cl_int _status; //!< Event status + mutable std::recursive_mutex _statusMutex; //!< Mutex for event status + mutable std::condition_variable_any _statusChanged; //!< Condition: event status changed + +private: + /*! + * \brief Triggers callbacks that have been registered for this event using \c setCallback. + * + * \param[in] status the command execution status for which the callbacks + * should be triggered for + */ + void triggerCallbacks( + cl_int status); + + /*! Saves a list of callbacks for each command execution status */ + std::map>> _callbacks; +}; + +#endif /* CL_EVENT_H_ */ diff --git a/icdpp/src/Kernel.cpp b/icdpp/src/Kernel.cpp new file mode 100644 index 0000000..8cab6f5 --- /dev/null +++ b/icdpp/src/Kernel.cpp @@ -0,0 +1,408 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Kernel.cpp + * + * \date 2011-06-08 + * \author Karsten Jeschkies + * \author Philipp Kegel + */ + +#include "Kernel.h" + +#include "Context.h" +#include "Device.h" +#include "Memory.h" +#include "Program.h" +#include "Retainable.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +_cl_kernel::_cl_kernel( + cl_program program, + const char *kernelName) : + _program(program) { + + if (!program) throw dclicd::Error(CL_INVALID_PROGRAM); + if (!kernelName) throw dclicd::Error(CL_INVALID_VALUE); + + try { + dclasio::message::CreateKernel request(_id, program->remoteId(), kernelName); + /* TODO Only create kernels on compute nodes where the associated program has been build. + * If no such compute nodes exists, throw CL_INVALID_PROGRAM_EXECUTABLE */ + dcl::executeCommand(program->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Kernel created (ID=" << _id + << ", name=" << kernelName + << ')' << std::endl; + + /* TODO Obtain function name and number of kernel arguments from response + * Use #args to create an appropriately sized _modifiedMemoryObjects */ + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + _program->retain(); +} + +_cl_kernel::_cl_kernel(dcl::object_id id, cl_program program) : + dcl::Remote(id), _program(program) { + assert(program != nullptr); // program must not be NULL + _program->retain(); +} + +_cl_kernel::~_cl_kernel() { + dclicd::release(_program); +} + +void _cl_kernel::destroy() { + assert(_ref_count == 0); + + try { + dclasio::message::DeleteKernel request(_id); + dcl::executeCommand(_program->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Kernel deleted (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +void _cl_kernel::setArgument(cl_uint index, size_t size, const void *value) { +// cl_uint numArgs; + std::unique_ptr request; + + /* Validate argument index using number of kernel arguments from kernel info */ +// getInfo(CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, nullptr); +// if (index >= numArgs) throw dclicd::Error(CL_INVALID_ARG_INDEX); + /* TODO Validate argument size using type name from kernel argument info (available as of OpenCL 1.2) */ + + /* TODO Determine argument type using type name and address qualifier from kernel argument info (available as of OpenCL 1.2) */ + + if (value == nullptr) { + /* argument could be buffer object which should initialized with NULL + * or could be declared with the __local qualifier */ + request.reset(new dclasio::message::SetKernelArgMemObject( + _id, index, size)); + } else { + if (size == sizeof(cl_mem)) { + /* value could be a pointer to buffer or image + * check if value points to valid memory object */ + cl_mem mem = _cl_mem::findMemObject(*((cl_mem *) value)); + if (mem) { + /* value points to memory object */ + request.reset(new dclasio::message::SetKernelArgMemObject( + _id, index, mem->remoteId())); + + if (mem->isOutput()) { + /* If a writable (CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE) + * memory object is set as kernel argument, it is assumed + * that the kernel will modify this memory object. */ + /* TODO Set appropriate size of memory object list during kernel creation */ +// assert(index < _writeMemoryObjects.size()); + if (_writeMemoryObjects.size() <= index) { + _writeMemoryObjects.resize(index + 1); + } + _writeMemoryObjects[index] = mem; + } + } + } + } + + if (!request) { + /* value points to a regular variable */ + request.reset(new dclasio::message::SetKernelArgBinary( + _id, index, size, value)); + } + + try { + dcl::executeCommand(_program->computeNodes(), *request); + dcl::util::Logger << dcl::util::Info + << "Kernel argument set (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +std::vector _cl_kernel::writeMemoryObjects() const { + std::set writeMemoryObjects; + + /* copy memory objects from argument list to set to remove duplicates */ + for (auto mem : _writeMemoryObjects) { + /* ignore empty (NULL) entries */ + if (mem) writeMemoryObjects.insert(mem); + } + + return std::vector(std::begin(writeMemoryObjects), + std::end(writeMemoryObjects)); +} + +/* + * Sends a 'create kernels in program' request to each compute node associated with program. + * + * All compute nodes receive a list of unique kernel IDs, which will be assigned + * to the created kernels on the compute node. + * If the number of kernel IDs is less than the number of kernels, an error + * (CL_INVALID_VALUE) is thrown. + */ +void _cl_kernel::createKernelsInProgram( + cl_program program, + std::vector& kernels) { + std::vector kernelIds; + cl_uint numKernels; + + if (!program) throw dclicd::Error(CL_INVALID_PROGRAM); + + /* _cl_program::getInfo will throw CL_INVALID_PROGRAM_EXECUTABLE if there + * is no successfully built executable for any device in program. */ + program->getInfo(CL_PROGRAM_NUM_KERNELS, sizeof(numKernels), &numKernels, nullptr); + + /* create kernel IDs */ + kernelIds.resize(numKernels); + for (unsigned int i = 0; i < numKernels; ++i) { + kernelIds[i] = dcl::Remote::generateId(); + } + + /* send command to compute nodes */ + try { + dclasio::message::CreateKernelsInProgram request(program->remoteId(), kernelIds); + /* TODO Only create kernels on compute nodes where the associated program has been build. + * If no such compute nodes exists, throw CL_INVALID_PROGRAM_EXECUTABLE */ + dcl::executeCommand(program->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Kernels in program created (program ID=" << program->remoteId() + << ", #kernels=" << numKernels + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + /* create kernels */ + kernels.resize(numKernels); + for (unsigned int i = 0; i < numKernels; ++i) { + kernels[i] = new _cl_kernel(kernelIds[i], program); + } +} + +cl_program _cl_kernel::program() const { + return _program; +} + +void _cl_kernel::getInfo( + cl_kernel_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_KERNEL_REFERENCE_COUNT: + dclicd::copy_info(_ref_count, param_value_size, param_value, + param_value_size_ret); + break; + case CL_KERNEL_CONTEXT: + dclicd::copy_info(_program->context(), param_value_size, param_value, + param_value_size_ret); + break; + case CL_KERNEL_PROGRAM: + dclicd::copy_info(_program, param_value_size, param_value, + param_value_size_ret); + break; + default: + { + std::lock_guard lock(_infoCacheMutex); + + auto i = _infoCache.find(param_name); // search kernel info in cache + if (i == std::end(_infoCache)) { + /* + * Cache miss: query info from compute node + * The kernel is on many compute nodes. Pick first one to query + * kernel info from. + */ + auto computeNode = _program->computeNodes().front(); + dclasio::message::GetKernelInfo request(_id, param_name); + + try { + std::unique_ptr response( + static_cast( + computeNode->executeCommand(request, dclasio::message::InfoResponse::TYPE).release())); + /* add kernel info to cache */ + i = _infoCache.insert(std::make_pair(param_name, response->param())).first; + + dcl::util::Logger << dcl::util::Info + << "Got kernel info (ID=" << _id + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + } + + dclicd::copy_info(i->second, param_value_size, param_value, + param_value_size_ret); + } + /* no break */ + } +} + +#if defined(CL_VERSION_1_2) +void _cl_kernel::getArgInfo( + cl_uint arg_indx, + cl_kernel_arg_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + assert(!"_cl_kernel::getArgInfo not implemented"); +} +#endif // #if defined(CL_VERSION_1_2) + +void _cl_kernel::getWorkGroupInfo( + cl_device_id device, + cl_kernel_work_group_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + if (!device) { + const std::vector& devices = _program->devices(); + if (devices.size() == 1) { + /* If only a single device is associated with this kernel (i.e. with + * its associated program) device can be NULL. */ + device = devices.front(); + } else { + throw dclicd::Error(CL_INVALID_DEVICE); + } + } else { + /* device must be associated with kernel, i.e. with is associated + * program */ + if (!_program->hasDevice(device)) { + throw dclicd::Error(CL_INVALID_DEVICE); + } + } + + { + std::lock_guard lock(_infoCacheMutex); + + /* (initialize and) obtain work group info cache for device */ + auto& infoCache = _workGroupInfoCaches[device]; + auto i = infoCache.find(param_name); // search work group info in cache + if (i == std::end(infoCache)) { + /* + * Cache miss: query work group info from compute node + */ + dcl::ComputeNode& computeNode = device->remote().getComputeNode(); + dclasio::message::GetKernelWorkGroupInfo request(_id, device->remote().getId(), param_name); + + try { + std::unique_ptr response( + static_cast( + computeNode.executeCommand(request, dclasio::message::InfoResponse::TYPE).release())); + /* add work group info to cache */ + i = infoCache.insert(std::make_pair(param_name, response->param())).first; + + dcl::util::Logger << dcl::util::Info + << "Got kernel work group info (kernel ID=" << _id + << ", device ID=" << device->remote().getId() + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + } + + dclicd::copy_info(i->second, param_value_size, param_value, + param_value_size_ret); + } +} diff --git a/icdpp/src/Kernel.h b/icdpp/src/Kernel.h new file mode 100644 index 0000000..05bbdb7 --- /dev/null +++ b/icdpp/src/Kernel.h @@ -0,0 +1,165 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Kernel.h + * + * \date 2011-06-08 + * \author Karsten Jeschkies + * \author Philipp Kegel + */ + +#ifndef CL_KERNEL_H_ +#define CL_KERNEL_H_ + +#include "Retainable.h" + +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include + + +class _cl_kernel: public _cl_retainable, public dcl::Remote { +public: + /*! + * \brief Creates kernel objects for all kernel functions in program. + * + * Kernel objects are not created for any \c __kernel functions in program + * that do not have the same function definition across all devices for + * which a program executable has been successfully built. + * + * \param[in] program the program from which the kernels should be created + * \param[in] kernels a list of kernels created from the program + */ + static void createKernelsInProgram( + cl_program program, + std::vector& kernels); + + + _cl_kernel( + cl_program program, + const char *kernelName); + virtual ~_cl_kernel(); + + cl_program program() const; + void getInfo( + cl_kernel_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + +#if defined(CL_VERSION_1_2) + void getArgInfo( + cl_uint arg_indx, + cl_kernel_arg_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; +#endif // #if defined(CL_VERSION_1_2) + + void getWorkGroupInfo( + cl_device_id device, + cl_kernel_work_group_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + /*! + * \brief Sets a kernel argument. + * + * \param[in] index index of the argument + * \param[in] size size of the argument value + * \param[in] value pointer to the argument value. + * Value may be NULL for memory objects and must be \c NULL for arguments + * for which the \c __local qualifier is specified. + */ + void setArgument( + cl_uint index, + size_t size, + const void *value = nullptr); + + /** + * @brief Returns the memory objects (possibly) written to with this kernel + * + * @return a list of memory objects + */ + std::vector writeMemoryObjects() const; + +protected: + void destroy(); + +private: + /*! + * \brief Private constructor setting ID of kernel object. + * + * Make sure that no kernel objects share the same ID! + * NOTE: This constructor does NOT create kernels on any compute node. + * Basically this constructor just sets all member variables. + * + * \param[in] id kernel ID + * \param[in] program program associated with kernel; must not be \c NULL + */ + _cl_kernel( + dcl::object_id id, + cl_program program); + + cl_program _program; + + /** Kernel info cache */ + mutable std::map _infoCache; + /** Work group info caches */ + mutable std::map> _workGroupInfoCaches; + mutable std::mutex _infoCacheMutex; + + /** + * @brief Memory objects modified by this kernel + */ + std::vector _writeMemoryObjects; +}; + +#endif /* CL_KERNEL_H_ */ diff --git a/icdpp/src/Memory.cpp b/icdpp/src/Memory.cpp new file mode 100644 index 0000000..81579b7 --- /dev/null +++ b/icdpp/src/Memory.cpp @@ -0,0 +1,416 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Memory.cpp + * + * @date 2011-08-21 + * @author Philipp Kegel + */ + +#if defined(linux) || defined(__linux) || defined(__linux__) +/* Feature test macro to enable posix_memalign in stdlib.h */ +#define _POSIX_C_SOURCE 200112L +#endif + +#include "Memory.h" + +#include "Context.h" +#include "Device.h" +#include "Retainable.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include "dclicd/detail/MappedMemory.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DCL_MEM_LOCK +#if defined(linux) || defined(__linux) || defined(__linux__) +#include +#include +#include +#endif +#endif +#if defined(linux) || defined(__linux) || defined(__linux__) +#include +#endif + + +std::set _cl_mem::_created_mem_obj; + +cl_mem _cl_mem::findMemObject(cl_mem ptr) { + auto i = std::find(std::begin(_created_mem_obj), std::end(_created_mem_obj), ptr); + return ((i == std::end(_created_mem_obj)) ? nullptr : ptr); +} + +_cl_mem::_cl_mem( + cl_context context, + cl_mem_flags flags, + size_t size, + void *host_ptr) : + _context(context), _flags(flags), _size(size), _host_ptr(host_ptr), _data(nullptr) { + /* Read-write mode of memory object */ + cl_mem_flags rwMode = flags & + (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY); + /* Allocate memory from host-accessible memory + * Host-accessible memory (e.g., PCIe memory) is part of the host memory + * that physically is accessible by both, host *and* device. + * In dOpenCL, this kind of memory could only be provided by highly + * sophisticated memory controllers that provide a uniform physical memory + * space across a network networks. + * However, in dOpenCL we take this flag as a hint to use page-locked host + * memory. */ + bool allocHostPtr = (flags & CL_MEM_ALLOC_HOST_PTR); + /* Copy or use memory referenced by host pointer */ + cl_mem_flags hostPtrMode = flags & + (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR); + + /* Validate context */ + if (!context) throw dclicd::Error(CL_INVALID_CONTEXT); + + /* TODO Assert 0 < size <= CL_DEVICE_MAX_MEM_ALLOC_SIZE */ + if (size == 0) throw dclicd::Error(CL_INVALID_BUFFER_SIZE); + + /* + * Validate flags + */ + /* Read-write flags are mutually exclusive; + * if no rwMode is given CL_MEM_READ_WRITE is the default */ + if (rwMode && + rwMode != CL_MEM_READ_WRITE && + rwMode != CL_MEM_READ_ONLY && + rwMode != CL_MEM_WRITE_ONLY) { + throw dclicd::Error(CL_INVALID_VALUE); + } + + /* Host pointer flags */ + if (host_ptr) { + switch (hostPtrMode) { + case CL_MEM_COPY_HOST_PTR: + /* allocate memory for copying the host pointer */ + allocHostMemory(); + /* TODO Copy data at host pointer to memory object's host memory */ + break; + case CL_MEM_USE_HOST_PTR: + /* CL_MEM_USE_HOST_PTR and CL_MEM_ALLOC_HOST_PTR are mutually + * exclusive */ + if (allocHostPtr) throw dclicd::Error(CL_INVALID_VALUE); + + /* Use memory referenced by host pointer as the storage bits for + * the memory object. + * Note that the OpenCL implementation is allowed to cache the + * memory object contents in device memory */ + _data = _host_ptr; + + /* TODO Update host data at synchronization points, if + * CL_MEM_USE_HOST_PTR is specified + * Copy data from compute node when clWaitForEvents or clFinish is + * called and affects an event or a command-queue that modified this + * memory object */ + break; + case (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR): + /* CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually + * exclusive */ + throw dclicd::Error(CL_INVALID_VALUE); + default: + /* Any of CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR must be set, + * if host pointer is not NULL */ + throw dclicd::Error(CL_INVALID_HOST_PTR); + } + } else { + /* CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR are only valid, if host + * pointer is not NULL */ + if (hostPtrMode) throw dclicd::Error(CL_INVALID_HOST_PTR); + } + + _context->retain(); + + /* Add memory object instance to list of memory object instances */ + bool inserted = _cl_mem::_created_mem_obj.insert(this).second; + assert(inserted); +} + +_cl_mem::~_cl_mem() { + freeHostMemory(); + + dclicd::release(_context); + + /* remove buffer from list of valid memory objects */ + _cl_mem::_created_mem_obj.erase(this); +} + +void _cl_mem::allocHostMemory() { + if (_data) return; // host pointer already allocated + +#if defined(linux) || defined(__linux) || defined(__linux__) + /* align memory to page boundaries in order to minimize the amount + * of required pages */ + int err = ::posix_memalign(&_data, ::sysconf(_SC_PAGESIZE), _size); + if (err != 0) throw dclicd::Error(CL_MEM_OBJECT_ALLOCATION_FAILURE); +#else /* Linux */ + _data = (void *) ::malloc(_size); + if (_data == nullptr) throw dclicd::Error(CL_MEM_OBJECT_ALLOCATION_FAILURE); +#endif /* Linux */ + + /* CL_MEM_ALLOC_HOST_PTR has been requested, page-lock the host memory + * for storing the memory object */ + if ((_flags & CL_MEM_ALLOC_HOST_PTR)) lockHostMemory(); +} + +void _cl_mem::freeHostMemory() { + if (!_data) return; // no host pointer allocated + + unlockHostMemory(); + + if (_data != _host_ptr) { + /* delete host memory data */ + ::free(_data); + } +} + +void _cl_mem::lockHostMemory() { +#ifdef DCL_MEM_LOCK + assert(_data != nullptr); + +#ifdef _POSIX_MEMLOCK_RANGE +#if defined(linux) || defined(__linux) || defined(__linux__) + struct rlimit mlock_limit; + + ::getrlimit(RLIMIT_MEMLOCK, &mlock_limit); + /* Linux automatically rounds addr (i.e., _data) to page boundaries. + * However, as this is not required by POSIX, a portable implementation + * must not rely on proper alignment of addr. */ + if (::mlock(_data, _size) != 0) { + /* memory locking failed */ + std::cerr << "Cannot lock host memory for memory object: " << strerror(errno) + << " (mlock limit cur=" << mlock_limit.rlim_cur + << " bytes, max=" << mlock_limit.rlim_max << " bytes)" << std::endl; + } +#endif /* Linux */ +#endif /* _POSIX_MEMLOCK_RANGE */ +#endif /* DCL_MEM_LOCK */ +} + +void _cl_mem::unlockHostMemory() { + if (!(_flags & CL_MEM_ALLOC_HOST_PTR)) return; // host memory has not been locked + +#ifdef DCL_MEM_LOCK + assert(_data != nullptr); + +#ifdef _POSIX_MEMLOCK_RANGE +#if defined(linux) || defined(__linux) || defined(__linux__) + /* Linux automatically rounds addr (i.e., _data) to page boundaries. + * However, as this is not required by POSIX, a portable implementation + * must not rely on proper alignment of addr. */ + if (::munlock(_data, _size) != 0) { + /* memory unlocking failed */ + std::cerr << "Could not unlock memory object in host memory: " + << strerror(errno) << std::endl; + } +#endif /* Linux */ +#endif /* _POSIX_MEMLOCK_RANGE */ +#endif /* DCL_MEM_LOCK */ +} + +void _cl_mem::destroy() { + assert(_ref_count == 0); + + /* execute destructor callbacks + * Callbacks must be executed *before* the memory object's resources are freed. */ + for (auto callback : _destructorCallbacks) { + callback.first(this, callback.second); + } + + try { + dclasio::message::DeleteMemory request(_id); + dcl::executeCommand(_context->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Memory object deleted (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +cl_context _cl_mem::context() const { + return _context; +} + +void _cl_mem::getInfo( + cl_mem_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_MEM_TYPE: + dclicd::copy_info(type(), param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_FLAGS: + dclicd::copy_info(_flags, param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_SIZE: + dclicd::copy_info(_size, param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_HOST_PTR: + dclicd::copy_info(_host_ptr, param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_MAP_COUNT: + dclicd::copy_info(mapCount(), param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_REFERENCE_COUNT: + dclicd::copy_info(_ref_count, param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_CONTEXT: + dclicd::copy_info(_context, param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_ASSOCIATED_MEMOBJECT: + dclicd::copy_info(associatedMemObject(), param_value_size, param_value, + param_value_size_ret); + break; + case CL_MEM_OFFSET: + dclicd::copy_info(offset(), param_value_size, param_value, + param_value_size_ret); + break; +// case CL_MEM_D3D10_RESOURCE_KHR: +// assert(!"cl_khr_d3d10_sharing not supported by dOpenCL"); +// break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +void _cl_mem::setDestructorCallback( + void (CL_CALLBACK *pfn_notify)(cl_mem, void *), void *user_data) { + _destructorCallbacks.push_back(std::make_pair(pfn_notify, user_data)); +} + +bool _cl_mem::isOutput() const { + return (_flags & (CL_MEM_WRITE_ONLY | CL_MEM_READ_WRITE)); +} + +void _cl_mem::onAcquireComplete(dcl::Process& destination, cl_int executionStatus) { + assert(executionStatus == CL_COMPLETE || executionStatus < 0); + + if (executionStatus == CL_COMPLETE) { + /* forward acquired memory object data to acquiring compute node */ + try { + destination.sendData(_size, _data); + } catch (const dcl::IOException& e) { + dcl::util::Logger << dcl::util::Error + << "(SYN) Acquire failed: " << e.what() + << std::endl; + } + } else { + dcl::util::Logger << dcl::util::Error + << "(SYN) Acquire failed: Data receipt failed" + << std::endl; + } +} + +void _cl_mem::onAcquire(dcl::Process& destination, dcl::Process& source) { + dcl::util::Logger << dcl::util::Debug + << "(SYN) Acquiring memory object from compute node '" << source.url() + << "' on behalf of compute node '" << destination.url() + << " (ID=" << remoteId() << ')' + << std::endl; + + /* acquire data from source compute node */ + /* FIXME Do not use memory object's host data cache for synchronizing compute node events + * A host maintains its own copy of a memory object (when allocated with + * CL_MEM_ALLOC_HOST_PTR) which must not be overwritten by possibly + * different copies that are exchanged during synchronization between + * compute nodes */ + try { + auto recv = acquire(source); + + /* forward memory object data to requesting compute node */ + recv->setCallback( + std::bind(&_cl_mem::onAcquireComplete, this, + std::ref(destination), std::placeholders::_1)); + } catch (const dcl::IOException& e) { + dcl::util::Logger << dcl::util::Error + << "(SYN) Acquire failed: " << e.what() + << std::endl; + } +} + +std::shared_ptr _cl_mem::acquire(dcl::Process& process) { + std::lock_guard lock(_dataMutex); + allocHostMemory(); + return process.receiveData(_size, _data); +} diff --git a/icdpp/src/Memory.h b/icdpp/src/Memory.h new file mode 100644 index 0000000..22a577c --- /dev/null +++ b/icdpp/src/Memory.h @@ -0,0 +1,230 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Memory.h + * + * @date 2011-08-21 + * @author Philipp Kegel + */ + +#ifndef CL_MEMORY_H_ +#define CL_MEMORY_H_ + +#include "Retainable.h" + +#include "dclicd/detail/MappedMemory.h" + +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + + +class _cl_mem: +public _cl_retainable, +public dcl::Remote { +public: + /** + * @brief Finds a valid dclicd::Memory object for a given cl_mem object. + * + * @param[in] ptr pointer to OpenCL memory object + * @return memory object, if the given pointer points to a valid memory object, otherwise \code NULL + */ + static cl_mem findMemObject( + cl_mem ptr); + + + virtual ~_cl_mem(); + + cl_context context() const; + void getInfo( + cl_mem_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + /** + * @brief Registers a user callback function with this memory object. + */ + void setDestructorCallback( + void (CL_CALLBACK * pfn_notify)( + cl_mem, void *), + void * user_data); + + /** + * @brief Tests, if this memory objects is writable + * + * @return @c true, if this memory object is writeable, otherwise @c false + */ + bool isOutput() const; + + /** + * @brief Unmaps a previously mapped region of a memory object. + * + * This method only discards the pointer to mapped memory but it does not + * unmap, i.e. copy data to a device. + * + * @param[in] mappedPtr + */ + virtual void unmap( + void *mappedPtr) = 0; + + + /** + * @brief Callback for a completed acquire operation. + * + * NOTE: This method is a work-around for missing node-to-node communication. + * When an acquire operation is completed which has been performed on behalf + * of a compute node the acquired data is forwarded to the requesting + * compute node. + * + * @param[in] destination the requesting compute node where the memory + * object has to be send to as an update + * @param[in] executionStatus + */ + void onAcquireComplete( + dcl::Process& destination, + cl_int executionStatus); + + /** + * @brief Callback for acquiring this memory object's data on behalf of a compute node + * + * NOTE: This method is a work-around for missing node-to-node communication. + * Rather than requesting a memory object's data from a compute node + * directly, the data is requested from the host which acquires that data + * from the compute node and forwards it to the requesting compute node. + * + * @param[in] destination the requesting compute node where the memory + * object has to be send to as an update + * @param[in] source the compute node owning the latest changes to + * this memory object + */ + void onAcquire( + dcl::Process& destination, + dcl::Process& source); + +protected: + _cl_mem(cl_context context, + cl_mem_flags flags, + size_t size, + void * host_ptr); + + /** + * @brief Allocates host memory for this memory object + */ + void allocHostMemory(); + + /** + * @brief Frees host memory that has been allocated for this memory object + */ + void freeHostMemory(); + + /** + * @brief Lock the pages holding this memory object in host memory. + */ + void lockHostMemory(); + + /** + * @brief Unlock the pages holding this memory object in host memory. + */ + void unlockHostMemory(); + + /** + * @brief Query memory object type. + * + * This method is reserved for internal use by @c _cl_mem::getInfo. + * + * @return the type of the command that is associated with this event + */ + virtual cl_mem_object_type type() const = 0; + + virtual cl_uint mapCount() const = 0; + + virtual cl_mem associatedMemObject() const = 0; + + virtual size_t offset() const = 0; + + void destroy(); + + /** + * @brief Acquires this memory object's data from a process (compute node). + * + * This method updates this memory object's data by downloading the latest + * bits from the specified compute node. + * + * @param[in] owner the process (a compute node) to acquire the memory + * object's data from + * @return a handle for the data transfer + */ + std::shared_ptr acquire( + dcl::Process& process); + + cl_context _context; + cl_mem_flags _flags; + size_t _size; + void *_host_ptr; /**< host_ptr argument specified, when memory object has been created */ + void *_data; /**< a cached copy of this memory object's data, used, e.g., for mapping */ + + mutable std::mutex _dataMutex; /**< Mutex for data; mostly used for mapping */ + + /** + * @brief Callbacks called when this memory object is destroyed. + * + * Access to this member cannot be synchronized in a sensible manner as a + * mutex variable would be destroyed together with the memory object. + */ + std::vector> _destructorCallbacks; + +private: + static std::set _created_mem_obj; /**< list of valid memory objects */ + /* TODO Synchronize access to _cl_mem::_created_mem_obj */ +}; + +#endif /* CL_MEMORY_H_ */ diff --git a/icdpp/src/Platform.cpp b/icdpp/src/Platform.cpp new file mode 100644 index 0000000..3601a37 --- /dev/null +++ b/icdpp/src/Platform.cpp @@ -0,0 +1,326 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Platform.cpp + * + * @date 2011-04-12 + * @author Philipp Kegel + */ + +#include "Platform.h" + +#include "ComputeNode.h" +#include "Device.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include + +#include + +#ifdef __APPLE__ +#include +#include +#include +#else +#include +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_DCL_NODE_FILE "dcl.nodes" + +namespace { + +void readNodeList( + std::vector& nodeList) { + const char *filename; + + nodeList.clear(); + + /* + * Determine node file + */ + filename = getenv("DCL_NODE_FILE"); + if (!filename || strlen(filename) == 0) { + filename = DEFAULT_DCL_NODE_FILE; + } + + std::ifstream ifs(filename); // open node file + if (ifs.good()) { + /* + * Parse node file + */ + do { + std::string str; + size_t pos; + + std::getline(ifs, str); + /* stop reading file on failure, but not if EOF has been reached */ + if (ifs.fail()) { + /* failbit is also set if EOF has been reached before any + * characters have been extracted; this is no error */ + if (ifs.eof()) break; + + /* true error */ + dcl::util::Logger << dcl::util::Error + << "Error reading node file '" << filename << '\'' << std::endl; + break; + } + + pos = str.find_first_of('#'); // find comment + if (pos != std::string::npos) str.resize(pos); // remove comment + boost::trim(str); // remove leading and trailing white spaces + if (!str.empty()) nodeList.push_back(str); + } while (ifs.good()); + + ifs.close(); // close node file + } else { + dcl::util::Logger << dcl::util::Warning + << "Node file '" << filename << "' not found" << std::endl; + } +} + +} /* unnamed namespace */ + +/******************************************************************************/ + +void _cl_platform_id::get( + std::vector& platforms) { + platforms.assign(1, dOpenCL()); +} + +_cl_platform_id::_cl_platform_id( + const std::string& profile, + const std::string& version, + const std::string& name, + const std::string& vendor, + const std::string& extensions) : + _profile(profile), _version(version), _name(name), + _vendor(vendor), _extensions(extensions), + _computeNodesInitialized(false) { + _communicationManager.reset(dcl::HostCommunicationManager::create()); + _communicationManager->start(); +} + +_cl_platform_id::~_cl_platform_id() { + /* + * Release all compute nodes + */ + { + std::lock_guard lock(_computeNodesMutex); + for (auto computeNode : _computeNodes) { + delete computeNode; + } + _computeNodes.clear(); + } + + /* shutdown connection manager */ + _communicationManager->stop(); +} + +cl_compute_node_WWU _cl_platform_id::createComputeNode( + const std::string& url, + void (*pfn_notify)( + cl_compute_node_WWU, cl_int, void *), + void *user_data) { + /* TODO Detect redundant connection + * Ensure that no redundant instance of _cl_compute_node_WWU is created for + * the same dcl::ComputeNode */ + auto remote = _communicationManager->createComputeNode(url); + auto computeNode = new _cl_compute_node_WWU( + this, *remote, pfn_notify, user_data); + + /* + * Add compute node to list + */ + { + std::lock_guard lock(_computeNodesMutex); + bool inserted = _computeNodes.insert(computeNode).second; + assert(inserted); + } + + return computeNode; +} + +void _cl_platform_id::destroyComputeNode(cl_compute_node_WWU computeNode) { + auto remote = &computeNode->remote(); + + /* + * Remove compute node from list + */ + { + std::lock_guard lock(_computeNodesMutex); + std::set::size_type numErased; + numErased = _computeNodes.erase(computeNode); + assert(numErased == 1); + } + + _communicationManager->destroyComputeNode(remote); + + delete computeNode; +} + +void _cl_platform_id::getComputeNodes( + std::vector& computeNodes) { + std::lock_guard lock(_computeNodesMutex); + + /* ensure that compute nodes from configuration file have been added to + * compute node list */ + initComputeNodes(); + + /* copy compute node list */ + computeNodes.assign(std::begin(_computeNodes), std::end(_computeNodes)); +} + +void _cl_platform_id::getDevices( + cl_device_type type, + std::vector& devices) { + std::vector computeNodes; + + /* Device type is validated in _cl_compute_node_WWU::getDevices */ + + getComputeNodes(computeNodes); + + devices.clear(); /* clear output list */ + + for (auto computeNode : computeNodes) { + std::vector nodeDevices; + + try { + computeNode->getDevices(type, nodeDevices); + devices.insert(std::end(devices), std::begin(nodeDevices), std::end(nodeDevices)); + } catch (dclicd::Error& err) { + if (err.err() == CL_DEVICE_NOT_FOUND) { + continue; /* ignore CL_DEVICE_NOT_FOUND */ + } + + throw; // rethrow error + } + } + + if (devices.empty()) throw dclicd::Error(CL_DEVICE_NOT_FOUND); +} + +void _cl_platform_id::getInfo( + cl_platform_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_PLATFORM_PROFILE: + dclicd::copy_info(_profile, param_value_size, param_value, param_value_size_ret); + break; + case CL_PLATFORM_VERSION: + dclicd::copy_info(_version, param_value_size, param_value, param_value_size_ret); + break; + case CL_PLATFORM_NAME: + dclicd::copy_info(_name, param_value_size, param_value, param_value_size_ret); + break; + case CL_PLATFORM_VENDOR: + dclicd::copy_info(_vendor, param_value_size, param_value, param_value_size_ret); + break; + case CL_PLATFORM_EXTENSIONS: + dclicd::copy_info(_extensions, param_value_size, param_value, param_value_size_ret); + break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +void _cl_platform_id::unloadCompiler() const { + /* TODO Implement _cl_platform_id::unloadCompiler */ +} + +dcl::HostCommunicationManager& _cl_platform_id::remote() const { + return *_communicationManager; +} + +void _cl_platform_id::initComputeNodes() { + std::vector urls; + + if (_computeNodesInitialized) return; // only process node file once + + readNodeList(urls); + + if (!urls.empty()) { + std::vector computeNodes; + + try { + /* Create compute node proxies */ + _communicationManager->createComputeNodes(urls, computeNodes); + + /* + * Create compute nodes and add to list + */ + for (auto computeNode : computeNodes) { + /* TODO Discard redundant connections + * Ensure that no redundant instance of _cl_compute_node_WWU is created for + * the same dcl::ComputeNode */ + bool inserted = _computeNodes.insert(new _cl_compute_node_WWU(this, *computeNode)).second; + assert(inserted); + } + + /* TODO Delete compute node proxies in case of an exception */ + } catch (const std::bad_alloc& err) { + dcl::util::Logger << dcl::util::Error + << "Out of memory" << std::endl; + } catch (const dcl::DCLException& err) { + dcl::util::Logger << dcl::util::Error + << "dOpenCL error: " << err.what() << std::endl; + } + } + + _computeNodesInitialized = true; +} diff --git a/icdpp/src/Platform.h b/icdpp/src/Platform.h new file mode 100644 index 0000000..0864455 --- /dev/null +++ b/icdpp/src/Platform.h @@ -0,0 +1,180 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Platform.h + * + * @date 2011-04-12 + * @author Philipp Kegel + */ + +#ifndef CL_PLATFORM_H_ +#define CL_PLATFORM_H_ + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +class _cl_platform_id { +public: + inline static cl_platform_id dOpenCL() { + static _cl_platform_id dOpenCL( + "FULL_PROFILE", + "OpenCL 1.1", + "dOpenCL", + "University of Muenster", + "cl_wwu_dcl cl_wwu_collective"); + return &dOpenCL; + } + + static void get( + std::vector& platforms); + + + virtual ~_cl_platform_id(); + + /** + * @brief Creates a compute node. + * + * The compute node is added to this platform and will be returned by + * getComputeNodes. + * + * @param[in] url the compute node's URL + * @param[in] pfn_notify A callback function that can be registered by the application. + * This callback function will be used by the OpenCL implementation to report information on errors that occur during communication with this compute node. + * This callback function may be called asynchronously by the OpenCL implementation. + * It is the application's responsibility to ensure that the callback function is thread-safe. + * If pfn_notify is NULL, no callback function is registered. + * @param[in] user_data + * @return a compute node + */ + cl_compute_node_WWU createComputeNode( + const std::string& url, + void (*pfn_notify)( + cl_compute_node_WWU compute_node, + cl_int errcode, + void * user_data) = 0, + void *user_data = nullptr); + + /** + * @brief Destroys a compute node. + * + * The compute node is removed from the platform. It will not be returned by + * a subsequent call of getComputeNodes. + * + * This method is reserved for internal use. Compute nodes should be + * released by an application using _cl_compute_node::release. + * + * @param[in] computeNode the compute node that should be remove from the platform + */ + void destroyComputeNode( + cl_compute_node_WWU computeNodes); + + /** + * @brief Obtain a list of all compute nodes. + * + * @param[out] computeNodes a list of compute nodes + */ + void getComputeNodes( + std::vector& computeNodes); + void getDevices( + cl_device_type deviceType, + std::vector& devices); + void getInfo( + cl_platform_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + void unloadCompiler() const; + + /** + * @brief Returns a reference to the remote platform instance. + */ + dcl::HostCommunicationManager& remote() const; + +private: + _cl_platform_id( + const std::string& profile, + const std::string& version, + const std::string& name, + const std::string& vendor, + const std::string& extensions); + + /* Platforms must be non-copyable */ + _cl_platform_id( + const _cl_platform_id& rhs) = delete; + _cl_platform_id& operator=( + const _cl_platform_id& rhs) = delete; + + /** + * @brief Initializes static compute nodes. + * + * This method must only be called while _computeNodesMutex is locked. + */ + void initComputeNodes(); + + + std::string _profile; + std::string _version; + std::string _name; + std::string _vendor; + std::string _extensions; + + std::unique_ptr _communicationManager; + + /** Indicates if static compute nodes have been added to this platform */ + bool _computeNodesInitialized; + /* TODO Use std::set> to store a platform's compute nodes */ + /** The compute nodes that are managed by this platform. */ + std::set _computeNodes; + mutable std::mutex _computeNodesMutex; +}; + +#endif /* CL_PLATFORM_H_ */ diff --git a/icdpp/src/Program.cpp b/icdpp/src/Program.cpp new file mode 100644 index 0000000..214eda7 --- /dev/null +++ b/icdpp/src/Program.cpp @@ -0,0 +1,542 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Program.cpp + * + * @date 2012-06-07 + * @author Karsten Jeschkies + * @author Philipp Kegel + */ + +#include "Program.h" + +#include "Context.h" +#include "Device.h" +#include "Retainable.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include "dclicd/detail/ProgramBuild.h" +#include "dclicd/detail/ProgramBuildInfo.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +_cl_program::_cl_program(cl_context context, const Sources& sources) : + _context(context), _isBuilt(false), _numKernels(0) +{ + if (!context) throw dclicd::Error(CL_INVALID_CONTEXT); + if (sources.empty()) throw dclicd::Error(CL_INVALID_VALUE); + + /* + * compute total lengths + */ + unsigned int totalLength = 0; + for (auto source : sources) { + totalLength += source.second; + } + + /* The compute nodes hosting this program are the compute nodes that host + * the program's context. */ + _computeNodes = _context->computeNodes(); + + /* + * concatenate strings + */ + _source.reserve(totalLength); + for (auto source : sources) { + _source.append(source.first, source.second); + } + + /* The devices associated with a program are the devices that are + * associated with a context, if a program is build from source. */ + _devices = _context->devices(); + _binaries.resize(_devices.size()); // _binaries must hold an entry for each device + + /* + * TODO Do not create program remotely before program build + * Creating a program currently is one of the most time-intensive operations + * in dOpenCL, as the program code is transferred to all compute nodes of a + * context. Deferring that data transfer to the time of program build reduces + * restricts data transfers to the compute nodes that the program is actually + * built for. + * Moreover, a deferred program build enables dOpenCL to correctly resolve + * include directives, as the list of include paths is not specified before + * compilation. Only if this list is known, dOpenCL can replace directives of + * the form '#include "..."' by the content of the found file, or by + * '#include<...>' statements to fallback to the default search on the compute + * node. + */ + + try { + dclasio::message::CreateProgramWithSource request( + _id, _context->remoteId(), totalLength); + + /* Send request and data */ + for (auto computeNode : _computeNodes) { + assert(computeNode != nullptr); + + computeNode->sendRequest(request); + /* Program code is sent using the data stream to avoid copying large + * program codes into a message before sending it. */ + computeNode->sendData(_source.size(), _source.data()); + } + + /* Await responses from all compute nodes */ + for (auto computeNode : _computeNodes) { + computeNode->awaitResponse(request); + /* TODO Receive responses from *all* compute nodes, i.e., do not stop receipt on first failure */ + } + + dcl::util::Logger << dcl::util::Info + << "Program created from source (ID=" << _id << ')' + << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + _context->retain(); +} + +_cl_program::_cl_program(cl_context context, + const std::vector& devices, const Binaries& binaries, + std::vector *binaryStatus) : + _context(context), _isBuilt(false), _numKernels(0) +{ + if (!context) throw dclicd::Error(CL_INVALID_CONTEXT); + if (devices.empty()) throw dclicd::Error(CL_INVALID_VALUE); + if (binaries.empty()) throw dclicd::Error(CL_INVALID_VALUE); + + /* + * Derive list of compute nodes from list of devices + * + * The compute nodes hosting this program are the compute nodes that host + * the program's devices. These compute nodes may be a subset of the compute + * nodes that host the program's context. + */ + { + std::set deviceNodes; + + for (auto device : _devices) { + deviceNodes.insert(&device->remote().getComputeNode()); + } + _computeNodes.assign(std::begin(deviceNodes), std::end(deviceNodes)); + } + + /* The devices associated with a program are the devices that a binary has + * been provided for, if a program is build from binaries. */ + _devices = devices; + _binaries.resize(_devices.size()); // _binaries must hold an entry for each device + + /* TODO Implement _cl_program constructor for binaries */ + assert(!"clCreateProgramFromBinaries not implemented"); + + _context->retain(); +} + +_cl_program::~_cl_program() { + dclicd::release(_context); +} + +void _cl_program::destroy() { + assert(_ref_count == 0); + + try { + dclasio::message::DeleteProgram request(_id); + dcl::executeCommand(_context->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "Program deleted (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +} + +const std::vector& _cl_program::computeNodes() const { + return _computeNodes; +} + +void _cl_program::build( + const std::vector *deviceList, + const char *options, + void (*pfn_notify)(cl_program, void *), + void *user_data) { + const std::vector& devices = deviceList ? *deviceList : _devices; + std::unique_ptr programBuild; + + if (deviceList && + !std::includes(std::begin(_devices), std::end(_devices), + std::begin(devices), std::end(devices))) { + /* At least one device in device list is not associated with program or NULL */ + throw dclicd::Error(CL_INVALID_DEVICE); + } + + /* TODO Check if a kernel is attached to this program + * Note that kernels may not be created on a daemon yet but have already been + * provided to the application. Hence, only the host can check this property. */ + + { + std::lock_guard lock(_buildStatusMutex); + + /* + * Check if a program build is pending for any device in deviceList + */ + for (auto& programBuild : _programBuilds) { + /* no program build must be pending for any device in deviceList */ + if (programBuild->includesAnyDeviceOf(std::begin(devices), std::end(devices))) { + if (!programBuild->isComplete()) throw dclicd::Error(CL_INVALID_OPERATION); + } + } + + /* Discard completed program builds */ + _programBuilds.erase( + std::remove_if(std::begin(_programBuilds), std::end(_programBuilds), + std::bind(&dclicd::detail::ProgramBuild::isComplete, std::placeholders::_1)), + std::end(_programBuilds)); + } + + /* TODO Pre-process program to replace includes using the '-I' compile options + * Locations for searching for header files are only valid on the host. + * Therefore, process include directives as follows: + * 1) '#include ' searches file in locations specified by '-I' and in + * the DCL_INCLUDE_PATHS environment variable. No other (standard) locations + * are searched, as standard locations are considered compiler-specific. + * 2) '#include "file"' searches file in the application's execution + * directory on the host. If file is not found, the directive is reprocessed + * as directive of the form '#include '. If file is still not found, + * the directive's quotes are replaced by angle bracket to transform it into + * a directive of the form '#include '. + * + * Correct pre-processing also has to take into account conditional includes + * and directives of the form '#include pp-token new-line', where pp-token + * is any valid pre-processor expression. */ + + /* TODO Remove '-I' compile options from the compile options string + * Location specified by '-I' are only valid on the host and thus must not + * be used by the daemons. */ + + try { + /* If not specified otherwise a program is build for all devices associated + * with the program */ + programBuild.reset(new dclicd::detail::ProgramBuild( + this, devices, options, pfn_notify, user_data)); + + /* TODO Send program code to the devices' compute nodes */ + } catch (const dcl::CLError& err) { + throw dclicd::Error(err); + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } + + if (pfn_notify == nullptr) { // build program synchronously + programBuild->wait(); // await completion of build operation + if (programBuild->hasFailed()) { + throw dclicd::Error(CL_BUILD_PROGRAM_FAILURE); + } + } else { + std::lock_guard lock(_buildStatusMutex); + _programBuilds.push_back(std::move(programBuild)); // add programBuild to list + } +} + +void _cl_program::compile( + const std::vector *deviceList, + const char *options, + const Headers *inputHeaders, + void (*pfn_notify)( + cl_program, void *), + void *user_data) { + assert(!"clCompileProgram not implemented"); +} + +cl_context _cl_program::context() const { + return _context; +} + +const std::vector& _cl_program::devices() const { + return _devices; +} + +void _cl_program::getInfo( + cl_program_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + switch (param_name) { + case CL_PROGRAM_REFERENCE_COUNT: + dclicd::copy_info(_ref_count, param_value_size, + param_value, param_value_size_ret); + break; + case CL_PROGRAM_CONTEXT: + dclicd::copy_info(_context, param_value_size, + param_value, param_value_size_ret); + break; + case CL_PROGRAM_NUM_DEVICES: + dclicd::copy_info(static_cast(_devices.size()), + param_value_size, param_value, param_value_size_ret); + break; + case CL_PROGRAM_DEVICES: + /* deep copy device list */ + dclicd::copy_info(_devices, param_value_size, param_value, + param_value_size_ret); + break; + case CL_PROGRAM_SOURCE: + dclicd::copy_info(_source.size() + 1, _source.c_str(), + param_value_size, param_value, param_value_size_ret); + break; + case CL_PROGRAM_BINARY_SIZES: + if (!_source.empty()) { + // program has been created with source + /* TODO Query binaries from devices */ + } + + if (param_value) { + /* The spec is not clear whether param_value points to an array or + * to the array's first element. We assume the latter as this + * assumption holds for other OpenCL implementations */ + auto binary_sizes = reinterpret_cast(param_value); + + if ((_devices.size() * sizeof(size_t)) > param_value_size) { + throw dclicd::Error(CL_INVALID_VALUE); + } + + /* copy binary sizes */ + for (unsigned int i = 0; i < _devices.size(); ++i) { + binary_sizes[i] = (_binaries[i].first ? _binaries[i].second : 0); + } + } + if (param_value_size_ret) { + *param_value_size_ret = (_devices.size() * sizeof(size_t)); + } + break; + case CL_PROGRAM_BINARIES: + if (!_source.empty()) { + // program has been created with source + /* TODO Query binaries from devices */ + } + + if (param_value) { + /* The spec is not clear whether param_value points to an array or + * to the array's first element. We assume the latter as this + * assumption holds for other OpenCL implementations */ + unsigned char **binaries = reinterpret_cast(param_value); + + if ((_devices.size() * sizeof(unsigned char *)) > param_value_size) { + throw dclicd::Error(CL_INVALID_VALUE); + } + + /* copy binaries */ + for (unsigned int i = 0; i < _devices.size(); ++i) { + /* Skip copying the program binary for a device identified by + * the array index, if the specific entry value in the array is + * NULL */ + if (binaries[i] == nullptr) continue; + /* Do not attempt to copy unavailable binaries */ + if (_binaries[i].first == nullptr) continue; + + memcpy(binaries[i], _binaries[i].first, _binaries[i].second); + } + } + if (param_value_size_ret) { + *param_value_size_ret = (_devices.size() * sizeof(unsigned char *)); + } + break; + /* CL_PROGRAM_NUM_KERNELS also is available in pre-OpenCL 1.1 environments + * by means of a definition in cl_wwu_dcl.h. */ + case CL_PROGRAM_NUM_KERNELS: + { + std::lock_guard lock(_buildStatusMutex); + + /* The number of kernels is also required if only OpenCL 1.1 should be + * supported. This number has to be known in advance when all kernels of + * a program should be created with clCreateKernelsInProgram. + * In OpenCL 1.1 it can be obtained by calling + * clCreateKernelsInProgram(program, 0, nullptr, &num_kernels) + * after building a program and returning this value to the host + * immediately. */ + if (_isBuilt) { + dclicd::copy_info(_numKernels, param_value_size, param_value, + param_value_size_ret); + } else { + throw dclicd::Error(CL_INVALID_PROGRAM_EXECUTABLE); + } + break; + } +#ifdef CL_VERSION_1_2 + case CL_PROGRAM_KERNEL_NAMES: + { + std::lock_guard lock(_buildStatusMutex); + + if (_isBuilt) { + dclicd::copy_info(_kernelNames, param_value_size, param_value, + param_value_size_ret); + } else { + throw dclicd::Error(CL_INVALID_PROGRAM_EXECUTABLE); + } + break; + } +#endif + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +void _cl_program::getBuildInfo( + cl_device_id device, + cl_program_build_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + if (std::find(std::begin(_devices), std::end(_devices), device) == std::end(_devices)) { + throw dclicd::Error(CL_INVALID_DEVICE); + } + + std::lock_guard lock(_buildStatusMutex); + /* (initialize and) obtain build info of program for device */ + auto& buildInfo = _buildInfo[device]; + + switch (param_name) { + case CL_PROGRAM_BUILD_STATUS: + dclicd::copy_info(buildInfo.status, param_value_size, param_value, + param_value_size_ret); + break; + case CL_PROGRAM_BUILD_OPTIONS: + dclicd::copy_info(buildInfo.options, param_value_size, param_value, + param_value_size_ret); + break; + case CL_PROGRAM_BUILD_LOG: + if (buildInfo.status == CL_BUILD_NONE) { + dclicd::copy_info("", param_value_size, param_value, + param_value_size_ret); + } else { + /* TODO Fully implement _cl_program::getBuildInfo */ + assert(!"_cl_program::getBuildInfo not fully implemented"); +#if 0 + /* + * Query build log from compute node + */ + try { + dclasio::message::GetProgramBuildLog request(_id, device->remote().id(), param_value_size); + std::unique_ptr response( + static_cast( + device->getComputeNode().executeCommand(request, dclasio::message::ProgramBuildLog::TYPE))); + + if (param_value) { + assert(size <= param_value_size); + /* Receive program build log (blocking operation) */ + device->getComputeNode().receiveData(response->size(), param_value)->wait(); + } + if (param_value_size_ret) { + *param_value_size_ret = response->size(); + } + } catch (const dcl::IOException& err) { + throw dclicd::Error(err); + } catch (const dcl::ProtocolException& err) { + throw dclicd::Error(err); + } +#endif + } + break; + default: + throw dclicd::Error(CL_INVALID_VALUE); + } +} + +bool _cl_program::hasDevice(cl_device_id device) const { + return (std::find(std::begin(_devices), std::end(_devices), device) != std::end(_devices)); +} + +void _cl_program::onBuildStatusChanged( + cl_device_id device, + cl_build_status status, + const std::string& options) { + std::lock_guard lock(_buildStatusMutex); + + /* Set \c _isBuilt to true if all compute nodes reported completion of program + * build, otherwise return */ + + /* TODO Update build status and save build info (status and options) for + * devices of completed (!) build operation + for (auto device : deviceList) { + _buildInfo[device] = dclicd::detail::ProgramBuildInfo(status, options); + } + */ +} diff --git a/icdpp/src/Program.h b/icdpp/src/Program.h new file mode 100644 index 0000000..4944c70 --- /dev/null +++ b/icdpp/src/Program.h @@ -0,0 +1,191 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Program.h + * + * @date 2012-06-07 + * @author Karsten Jeschkies + * @author Philipp Kegel + */ + +#ifndef CL_PROGRAM_H_ +#define CL_PROGRAM_H_ + +#include "Retainable.h" + +#include "dclicd/detail/ProgramBuild.h" +#include "dclicd/detail/ProgramBuildInfo.h" + +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + + +class _cl_program: + public _cl_retainable, + public dcl::Remote { +public: + typedef std::vector> Binaries; + typedef std::vector> Sources; + typedef std::map Headers; + + + _cl_program( + cl_context context, + const Sources& sources); + _cl_program( + cl_context context, + const std::vector& devices, + const Binaries& binaries, + std::vector * binaryStatus); + virtual ~_cl_program(); + + /** + * @brief Obtain a list of all compute nodes belonging to devices the program is built for. + * + * @return a list of compute nodes + */ + const std::vector& computeNodes() const; + + /** + * @brief Builds (compiles and links) a program executable from the program source or binary. + * + * No changes to the program executable are allowed while there are kernels + * associated with a program object. Therefore, calls to this method must + * return CL_INVALID_OPERATION if there are kernels attached to this + * program. + */ + void build( + const std::vector * deviceList, + const char * options, + void (*pfn_notify)( + cl_program, void *), + void * user_data); + + /** + * @brief Compiles a program's source for all the devices or a specific device(s) in the OpenCL context associated with @c program. + * + * @param deviceList + * @param options + * @param inputHeaders + * @param pfn_notify + * @param user_data + */ + void compile( + const std::vector *devices, + const char * options, + const Headers * inputHeaders, + void (*pfn_notify)( + cl_program, void *), + void * user_data); + + cl_context context() const; + const std::vector& devices() const; + void getInfo( + cl_program_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + void getBuildInfo( + cl_device_id, + cl_program_build_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + bool hasDevice( + cl_device_id device) const; + + /** + * @brief Callback method to indicate build status changes. + * + * This method is called by a ProgramBuild object to add build info to this + * program. + * + * @param[in] device the device this program has been build for + * @param[in] status build status + * @param[in] options build options + */ + void onBuildStatusChanged( + cl_device_id device, + cl_build_status status, + const std::string& options); + +protected: + void destroy(); + +private: + void init(); + + std::vector _computeNodes; /**< compute nodes hosting this program */ + + cl_context _context; /**< Context associated with this program */ + std::string _source; /**< Concatenated program sources */ + std::vector _devices; /**< Devices associated with this program */ + Binaries _binaries; /**< Program binaries */ + /** + * @brief Build status + * @c true, if program a program executable has been built successfully for + * at least one device in the list of devices associated with program. */ + bool _isBuilt; + cl_uint _numKernels; /**< number of kernels in program */ +#ifdef CL_VERSION_1_2 + std::string _kernelNames; /**< a semi-colon separated list of kernel names in program */ +#endif + + std::list> _programBuilds; /**< Pending programBuilds */ + + mutable std::map _buildInfo; /**< Build info of program (cached) */ + mutable std::mutex _buildStatusMutex; +}; + +#endif /* CL_PROGRAM_H_ */ diff --git a/icdpp/src/Retainable.cpp b/icdpp/src/Retainable.cpp new file mode 100644 index 0000000..7abb046 --- /dev/null +++ b/icdpp/src/Retainable.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Retainable.cpp + * + * @date 2011-05-18 + * @author Louay Hashim + * @author Philipp Kegel + */ + +#include "Retainable.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +_cl_retainable::_cl_retainable() : _ref_count(1) { } + +_cl_retainable::~_cl_retainable() { } + +void _cl_retainable::retain() { + /* Atomically increase reference count */ + ++_ref_count; +} + +bool _cl_retainable::release() { + cl_uint refCount; + + /* Atomically decrease reference count */ + refCount = _ref_count--; + assert(refCount > 0); // _ref_count must be greater than zero when calling release + + if (refCount == 1) destroy(); + + return (refCount == 1); +} diff --git a/icdpp/src/Retainable.h b/icdpp/src/Retainable.h new file mode 100644 index 0000000..300ef37 --- /dev/null +++ b/icdpp/src/Retainable.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Retainable.h + * + * @date 2011-05-18 + * @author Louay Hashim + * @author Philipp Kegel + */ + +#ifndef CL_RETAINABLE_H_ +#define CL_RETAINABLE_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +class _cl_retainable { +public: + /** + * @brief Creates a retainable object. + * + * The object is retained implicitly, i.e., the reference counter is set to 1. + */ + _cl_retainable(); + virtual ~_cl_retainable(); + + /** + * @brief Increases this object's reference count by one. + */ + virtual void retain(); + + /** + * @brief Decreases this object's reference count by one. + * + * This object is destroyed, if its reference count becomes zero. + * + * @return @c true, if this object has been destroyed, otherwise @c false + */ + virtual bool release(); + +protected: + virtual void destroy() = 0; + + std::atomic _ref_count; +}; + +#endif /* CL_RETAINABLE_H_ */ diff --git a/icdpp/src/cl.cpp b/icdpp/src/cl.cpp new file mode 100644 index 0000000..e1feb8d --- /dev/null +++ b/icdpp/src/cl.cpp @@ -0,0 +1,1556 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl.cpp + * + * @date 2011-04-12 + * @author Philipp Kegel + * + * @brief Implementation of the OpenCL API + * + * Function calls of the C API are redirected to corresponding method of a C++ + * implementation. Functions in this file only perform type conversions and + * related operations, e.g. validating list parameters that are converted into + * vectors. The C++ methods validate parameters. + */ + +#include "CommandQueue.h" +#include "ComputeNode.h" +#include "Context.h" +#include "Device.h" +#include "Event.h" +#include "Kernel.h" +#include "Memory.h" +#include "Platform.h" +#include "Program.h" +#include "Retainable.h" + +#include "dclicd/Buffer.h" +#include "dclicd/Error.h" +#include "dclicd/Event.h" +#include "dclicd/utility.h" + +#include "dclicd/detail/ContextProperties.h" + +#ifdef __APPLE__ +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if !defined(CL_VERSION_1_2) +/* Declare OpenCL 1.2 APIs as local helper functions. + * These APIs are used internally to implement OpenCL 1.1 APIs (see end of this file). */ +cl_int clEnqueueMarkerWithWaitList( + cl_command_queue command_queue, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event); + +cl_int clEnqueueBarrierWithWaitList( + cl_command_queue command_queue, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event); + +void * clGetExtensionFunctionAddressForPlatform( + cl_platform_id platform, + const char * func_name); +#endif // #if !defined(CL_VERSION_1_2) + +namespace { + +template struct ErrorCode; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_DEVICE; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_PLATFORM; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_CONTEXT; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_COMMAND_QUEUE; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_MEM_OBJECT; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_PROGRAM; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_KERNEL; }; +template<> struct ErrorCode { static const cl_int INVALID_OBJECT = CL_INVALID_EVENT; }; + +template +inline cl_int clRetain(CLObject object) { + if (!object) + return ErrorCode::INVALID_OBJECT; + + object->retain(); + return CL_SUCCESS; +} + +template +inline cl_int clRelease(CLObject object) { + if (!object) + return ErrorCode::INVALID_OBJECT; + + try { + dclicd::release(object); + return CL_SUCCESS; + } catch (const dclicd::Error& err) { + return err.err(); + } +} + +template +inline cl_int clGetInfo( + CLObject object, cl_context_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + if (!object) + return ErrorCode::INVALID_OBJECT; + + try { + object->getInfo(param_name, param_value_size, param_value, + param_value_size_ret); + return CL_SUCCESS; + } catch (const dclicd::Error& err) { + return err.err(); + } +} + +} // anonymous namespace + +/******************************************************************************/ + +/* Platform APIs */ +cl_int clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms, + cl_uint *num_platforms) { + if (platforms) { + if (num_entries == 0) return CL_INVALID_VALUE; + } else { + if (!num_platforms) return CL_INVALID_VALUE; + } + + try { + std::vector platforms_; + + _cl_platform_id::get(platforms_); + + if (platforms) { + auto platform = std::begin(platforms_); + for (cl_uint i = 0; i < num_entries && platform != std::end(platforms_); ++i) { + *platforms++ = *platform++; + } + } + if (num_platforms) *num_platforms = platforms_.size(); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clGetPlatformInfo(cl_platform_id platform, cl_platform_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + return clGetInfo( + platform ? platform : _cl_platform_id::dOpenCL(), + param_name, param_value_size, param_value, param_value_size_ret); +} + +/* Device APIs */ +cl_int clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type, + cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices) { + if (platform) { + /* TODO Validate platform */ + } else { + /* Behavior is implementation defined, if platform is NULL */ + platform = _cl_platform_id::dOpenCL(); + } + + if (devices) { + if (num_entries == 0) return CL_INVALID_VALUE; + } else { + if (!num_devices) return CL_INVALID_VALUE; + } + + try { + std::vector devices_; + + platform->getDevices(device_type, devices_); + + if (devices) { + auto device = std::begin(devices_); + for (cl_uint i = 0; i < num_entries && device != std::end(devices_); ++i) { + *devices++ = *device++; + } + } + if (num_devices) *num_devices = devices_.size(); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clGetDeviceInfo(cl_device_id device, cl_device_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + return clGetInfo(device, param_name, param_value_size, param_value, param_value_size_ret); +} + +#if defined(CL_VERSION_1_2) +cl_int clCreateSubDevices( + cl_device_id in_device, + const cl_device_partition_property *properties, + cl_uint num_devices, + cl_device_id *out_devices, + cl_uint *num_devices_ret) { + assert(!"clCreateSubDevices not implemented"); + return CL_SUCCESS; +} + +cl_int clRetainDevice(cl_device_id device) { + assert(!"clRetainDevice not implemented"); + return CL_SUCCESS; +} + +cl_int clReleaseDevice(cl_device_id device) { + assert(!"clReleaseDevice not implemented"); + return CL_SUCCESS; +} +#endif // #if defined(CL_VERSION_1_2) + +/* Context APIs */ +cl_context clCreateContext(const cl_context_properties *properties, + cl_uint num_devices, const cl_device_id *devices, void(*pfn_notify)( + const char *errinfo, const void *private_info, size_t cb, + void *user_data), void *user_data, cl_int *errcode_ret) { + cl_context context = nullptr; + cl_int errcode = CL_SUCCESS; + + /* + * Validate device list + */ + if (num_devices == 0 || !devices) { + errcode = CL_INVALID_VALUE; + } + + /* + * Create context + */ + if (errcode == CL_SUCCESS) { + try { + std::unique_ptr properties_; + if (properties) properties_.reset(new dclicd::detail::ContextProperties(properties)); + + context = new _cl_context(properties_.get(), + std::vector(devices, devices + num_devices), + pfn_notify, user_data); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return context; +} + +cl_context clCreateContextFromType(const cl_context_properties *properties, + cl_device_type device_type, void(*pfn_notify)(const char *errinfo, + const void *private_info, size_t cb, void *user_data), + void *user_data, cl_int *errcode_ret) { + cl_context context = nullptr; + cl_int errcode = CL_SUCCESS; + + /* + * Create context + */ + try { + std::unique_ptr properties_; + if (properties) properties_.reset(new dclicd::detail::ContextProperties(properties)); + + context = new _cl_context(properties_.get(), device_type, pfn_notify, + user_data); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc& err) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return context; +} + +cl_int clRetainContext(cl_context context) { + return clRetain(context); +} + +cl_int clReleaseContext(cl_context context) { + return clRelease(context); +} + +cl_int clGetContextInfo(cl_context context, cl_context_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + return clGetInfo(context, param_name, param_value_size, param_value, param_value_size_ret); +} + +/* Command Queue APIs */ +cl_command_queue clCreateCommandQueue(cl_context context, cl_device_id device, + cl_command_queue_properties properties, cl_int *errcode_ret) { + cl_command_queue command_queue = nullptr; + cl_int errcode = CL_SUCCESS; + + try { + command_queue = new _cl_command_queue(context, device, properties); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return command_queue; +} + +cl_int clRetainCommandQueue(cl_command_queue command_queue) { + return clRetain(command_queue); +} + +cl_int clReleaseCommandQueue(cl_command_queue command_queue) { + return clRelease(command_queue); +} + +cl_int clGetCommandQueueInfo(cl_command_queue command_queue, + cl_command_queue_info param_name, size_t param_value_size, + void *param_value, size_t *param_value_size_ret) { + return clGetInfo(command_queue, param_name, param_value_size, param_value, param_value_size_ret); +} + +#if defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS) || (defined(CL_VERSION_1_0) && !defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +cl_int clSetCommandQueueProperty( + cl_command_queue command_queue, + cl_command_queue_properties properties, + cl_bool enable, + cl_command_queue_properties *old_properties) { + /* clSetCommandQueueProperty is deprecated since OpenCL 1.1 and will not be + * implemented in dOpenCL */ + assert(!"clSetCommandQueueProperty not implemented"); + return CL_SUCCESS; +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS) + +/* Memory Object APIs */ +cl_mem clCreateBuffer(cl_context context, cl_mem_flags flags, size_t size, + void *host_ptr, cl_int *errcode_ret) { + cl_mem buffer = nullptr; + cl_int errcode = CL_SUCCESS; + + try { + buffer = new dclicd::Buffer(context, flags, size, host_ptr); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return buffer; +} + +cl_mem clCreateSubBuffer( + cl_mem buffer, + cl_mem_flags flags, + cl_buffer_create_type buffer_create_type, + const void *buffer_create_info, + cl_int *errcode_ret) { + assert(!"clCreateSubBuffer not implemented"); + return nullptr; +} + +cl_int clRetainMemObject(cl_mem memobj) { + return clRetain(memobj); +} + +cl_int clReleaseMemObject(cl_mem memobj) { + return clRelease(memobj); +} + +cl_int clGetSupportedImageFormats( + cl_context context, + cl_mem_flags flags, + cl_mem_object_type image_type, + cl_uint num_entries, + cl_image_format *image_formats, + cl_uint *num_image_formats) { + if (!context) return CL_INVALID_CONTEXT; + + if (image_formats) { + if (num_entries == 0) return CL_INVALID_VALUE; +// The spec does not define behavior if image_formats and num_image_formats are NULL +// } else { +// if (!num_image_formats) return CL_INVALID_VALUE; + } + + try { + std::vector imageFormats_; + + context->getSupportedImageFormats(flags, image_type, imageFormats_); + + if (image_formats) { + auto imageFormat = std::begin(imageFormats_); + for (cl_uint i = 0; i < num_entries && imageFormat != std::end(imageFormats_); ++i) { + *image_formats++ = *imageFormat++; + } + } + if (num_image_formats) *num_image_formats = imageFormats_.size(); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clGetMemObjectInfo(cl_mem mem, + cl_mem_info param_name, size_t param_value_size, + void *param_value, size_t *param_value_size_ret) { + return clGetInfo(mem, param_name, param_value_size, param_value, param_value_size_ret); +} + +cl_int clSetMemObjectDestructorCallback(cl_mem memobj, + void (CL_CALLBACK *pfn_notify)(cl_mem, void *), + void *user_data) { + if (memobj) { + try { + memobj->setDestructorCallback(pfn_notify, user_data); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_MEM_OBJECT; + } + + return CL_SUCCESS; +} + +/* Sampler APIs */ + +/* Program Object APIs */ +cl_program clCreateProgramWithSource(cl_context context, cl_uint count, + const char **strings, const size_t *lengths, cl_int *errcode_ret) { + cl_program program = nullptr; + cl_int errcode = CL_SUCCESS; + _cl_program::Sources sources; + + if (!strings) { + if (errcode_ret) { + *errcode_ret = CL_INVALID_VALUE; + } + return program; + } + + /* + * Create sources from C strings + */ + if (lengths) { + for (unsigned int i = 0; i < count; ++i) { + if (!strings[i]) { + if (errcode_ret) { + *errcode_ret = CL_INVALID_VALUE; + } + return program; + } + + if (lengths[i] == 0) { + /* string is NULL terminated */ + sources.push_back(std::make_pair(strings[i], strlen(strings[i]))); + } else { + sources.push_back(std::make_pair(strings[i], lengths[i])); + } + } + } else { + for (unsigned int i = 0; i < count; ++i) { + if (!strings[i]) { + if (errcode_ret) { + *errcode_ret = CL_INVALID_VALUE; + } + return program; + } + + sources.push_back(std::make_pair(strings[i], strlen(strings[i]))); + } + } + + try { + program = new _cl_program(context, sources); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return program; +} + +cl_program clCreateProgramWithBinary( + cl_context context, + cl_uint num_devices, + const cl_device_id *device_list, + const size_t *lengths, + const unsigned char **bytes, + cl_int *binary_status, + cl_int *errcode_ret) { + cl_program program = nullptr; + cl_int errcode = CL_SUCCESS; + _cl_program::Binaries binaries; + + if (num_devices == 0 || !device_list || + !lengths || + !bytes) { + if (errcode_ret) { + *errcode_ret = CL_INVALID_VALUE; + } + return program; + } + + /* + * Create binaries from bytes + */ + binaries.reserve(num_devices); + for (unsigned int i = 0; i < num_devices; ++i) { + if (!lengths[i] || !bytes[i]) { + if (errcode_ret) { + *errcode_ret = CL_INVALID_VALUE; + } + return program; + } + + binaries.push_back(std::make_pair(bytes[i], lengths[i])); + } + + try { + std::vector binaryStatus; + + program = new _cl_program(context, + std::vector(device_list, device_list + num_devices), + binaries, + (binary_status ? &binaryStatus : nullptr)); + + /* IMPORTANT: binary status must also be returned if CL_INVALID_BINARY + * is raised */ + assert(binaryStatus.size() == num_devices); + if (binary_status) { + std::copy(std::begin(binaryStatus), std::end(binaryStatus), binary_status); + } + + errcode = CL_SUCCESS; + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return program; +} + +#if defined(CL_VERSION_1_2) +cl_program clCreateProgramWithBuiltInKernels( + cl_context context, + cl_uint num_devices, + const cl_device_id *device_list, + const char *kernel_names, + cl_int *errcode_ret) { + assert(!"clCreateProgramWithBuiltInKernels not implemented"); + return nullptr; +} +#endif // #if defined(CL_VERSION_1_2) + +cl_int clRetainProgram(cl_program program) { + return clRetain(program); +} + +cl_int clReleaseProgram(cl_program program) { + return clRelease(program); +} + +cl_int clBuildProgram(cl_program program, cl_uint num_devices, + const cl_device_id *device_list, const char *options, + void(*pfn_notify)(cl_program, void *), void *user_data) { + std::unique_ptr> _devices; + cl_int errcode = CL_SUCCESS; + + if (!program) return CL_INVALID_PROGRAM; + + if ((!device_list && num_devices > 0) || + (device_list && num_devices == 0)) { + return CL_INVALID_VALUE; + } + + /* + * Convert device list + */ + if (device_list) { + _devices.reset(new std::vector(device_list, + device_list + num_devices)); + } + + /* + * Build program + */ + try { + // be generous and accept NULL pointer as options + program->build(_devices.get(), options, pfn_notify, user_data); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } + + return errcode; +} + +#if defined(CL_VERSION_1_2) +cl_int clCompileProgram( + cl_program program, + cl_uint num_devices, + const cl_device_id * device_list, + const char * options, + cl_uint num_input_headers, + const cl_program * input_headers, + const char ** header_include_names, + void(CL_CALLBACK * pfn_notify)(cl_program, void *), + void * user_data) { + std::unique_ptr> _devices; + std::unique_ptr<_cl_program::Headers> _inputHeaders; + cl_int errcode = CL_SUCCESS; + + if (!program) return CL_INVALID_PROGRAM; + + if ((!device_list && num_devices > 0) || + (device_list && num_devices == 0)) { + return CL_INVALID_VALUE; + } + + if ((!input_headers && !header_include_names && num_input_headers > 0) || + ((input_headers || header_include_names) && num_input_headers == 0)) { + return CL_INVALID_VALUE; + } + + /* + * Convert device list + */ + if (device_list) { + _devices.reset(new std::vector(device_list, + device_list + num_devices)); + } + + /* + * Convert input header list + */ + if (input_headers) { + _inputHeaders.reset(new _cl_program::Headers()); + for (unsigned int i = 0; i < num_input_headers; ++i) { + _inputHeaders->insert(std::make_pair(header_include_names[i], input_headers[i])); + } + } + + /* + * Compile program + */ + try { + // be generous and accept nullptr as options + program->compile(_devices.get(), options, _inputHeaders.get(), pfn_notify, user_data); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } + + return errcode; +} + +cl_program clLinkProgram( + cl_context context, + cl_uint num_devices, + const cl_device_id * device_list, + const char * options, + cl_uint num_input_programs, + const cl_program * input_programs, + void(CL_CALLBACK * pfn_notify)(cl_program, void *), + void * user_data, + cl_int * errcode_ret) { + assert(!"clLinkProgram not implemented"); + return nullptr; +} +#endif // #if defined(CL_VERSION_1_2) + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +cl_int clUnloadCompiler(void) { + /* clUnloadCompiler is deprecated since OpenCL 1.2 and is implemented as a + * no-operation in dOpenCL */ + return CL_SUCCESS; +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +cl_int clUnloadPlatformCompiler(cl_platform_id platform) { + if (platform) { + platform->unloadCompiler(); + } else { + return CL_INVALID_PLATFORM; + } + + return CL_SUCCESS; +} + +cl_int clGetProgramInfo(cl_program program, cl_program_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + return clGetInfo(program, param_name, param_value_size, param_value, param_value_size_ret); +} + +cl_int clGetProgramBuildInfo(cl_program program, cl_device_id device, + cl_program_build_info param_name, size_t param_value_size, + void *param_value, size_t *param_value_size_ret) { + if (program) { + try { + program->getBuildInfo(device, param_name, param_value_size, + param_value, param_value_size_ret); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_PROGRAM; + } + + return CL_SUCCESS; +} + +/* Kernel Object APIs */ +cl_kernel clCreateKernel(cl_program program, const char *kernel_name, + cl_int *errcode_ret) { + cl_kernel kernel = nullptr; + cl_int errcode = CL_SUCCESS; + + if (!kernel_name) { + if (errcode_ret) { + *errcode_ret = CL_INVALID_VALUE; + } + return kernel; + } + + try { + kernel = new _cl_kernel(program, kernel_name); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return kernel; +} + +cl_int clCreateKernelsInProgram(cl_program program, cl_uint num_kernels, + cl_kernel *kernels, cl_uint *num_kernels_ret) { + if (!program) return CL_INVALID_PROGRAM; + if (!kernels && (num_kernels > 0)) return CL_INVALID_VALUE; + + try { + cl_uint num_kernels_in_program; + + /* Query number of kernels from program */ + program->getInfo(CL_PROGRAM_NUM_KERNELS, sizeof(num_kernels_in_program), + &num_kernels_in_program, nullptr); + + if (kernels) { + std::vector kernels_; + + if (num_kernels < num_kernels_in_program) return CL_INVALID_VALUE; + + _cl_kernel::createKernelsInProgram(program, kernels_); + assert(num_kernels >= kernels_.size()); + + /* Copy kernels */ + std::copy(std::begin(kernels_), std::end(kernels_), kernels); + } + + if (num_kernels_ret) { + *num_kernels_ret = num_kernels_in_program; + } + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + return CL_OUT_OF_HOST_MEMORY; + } + + return CL_SUCCESS; +} + +cl_int clRetainKernel(cl_kernel kernel) { + return clRetain(kernel); +} + +cl_int clReleaseKernel(cl_kernel kernel) { + return clRelease(kernel); +} + +cl_int clSetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, + const void *arg_value) { + if (kernel) { + try { + kernel->setArgument(arg_index, arg_size, arg_value); + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + return CL_OUT_OF_HOST_MEMORY; + } + } else { + return CL_INVALID_KERNEL; + } + + return CL_SUCCESS; +} + +cl_int clGetKernelInfo(cl_kernel kernel, cl_kernel_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + return clGetInfo(kernel, param_name, param_value_size, param_value, param_value_size_ret); +} + +#if defined(CL_VERSION_1_2) +cl_int clGetKernelArgInfo( + cl_kernel kernel, + cl_uint arg_indx, + cl_kernel_arg_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) { + if (kernel) { + try { + kernel->getArgInfo(arg_indx, param_name, param_value_size, + param_value, param_value_size_ret); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_KERNEL; + } + + return CL_SUCCESS; +} +#endif // #if defined(CL_VERSION_1_2) + +cl_int clGetKernelWorkGroupInfo( + cl_kernel kernel, + cl_device_id device, + cl_kernel_work_group_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) { + if (kernel) { + try { + kernel->getWorkGroupInfo(device, param_name, param_value_size, + param_value, param_value_size_ret); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_KERNEL; + } + + return CL_SUCCESS; +} + +/* Event Object APIs */ +cl_int clWaitForEvents(cl_uint num_events, const cl_event *event_list) { + if (num_events == 0 || !event_list) { + return CL_INVALID_VALUE; + } + + try { + _cl_event::waitForEvents(std::vector(event_list, + event_list + num_events)); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clGetEventInfo(cl_event event, cl_profiling_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + return clGetInfo(event, param_name, param_value_size, param_value, param_value_size_ret); +} + +cl_int clRetainEvent(cl_event event) { + return clRetain(event); +} + +cl_int clReleaseEvent(cl_event event) { + return clRelease(event); +} + +cl_event clCreateUserEvent(cl_context context, cl_int *errcode_ret) { + cl_event event = nullptr; + cl_int errcode = CL_SUCCESS; + + try { + event = new dclicd::UserEvent(context); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return event; +} + +cl_int clSetUserEventStatus(cl_event event, cl_int execution_status) { + dclicd::UserEvent *user_event = dynamic_cast(event); + + if (user_event) { + try { + user_event->setStatus(execution_status); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_EVENT; + } + + return CL_SUCCESS; +} + +cl_int clSetEventCallback( + cl_event event, + cl_int command_exec_callback_type, + void (CL_CALLBACK *pfn_event_notify)( + cl_event event, + cl_int event_command_exec_status, + void *user_data), + void * user_data) { + if (event) { + try { + event->setCallback( + command_exec_callback_type, pfn_event_notify, user_data); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_EVENT; + } + + return CL_SUCCESS; +} + +/* Profiling APIs */ +cl_int clGetEventProfilingInfo(cl_event event, cl_profiling_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + if (event) { + try { + event->getProfilingInfo(param_name, param_value_size, param_value, + param_value_size_ret); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_EVENT; + } + + return CL_SUCCESS; +} + +/* Flush and Finish APIs */ +cl_int clFlush(cl_command_queue command_queue) { + if (command_queue) { + try { + command_queue->flush(); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_COMMAND_QUEUE; + } + + return CL_SUCCESS; +} + +cl_int clFinish(cl_command_queue command_queue) { + if (command_queue) { + try { + command_queue->finish(); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_COMMAND_QUEUE; + } + + return CL_SUCCESS; +} + +/* Enqueued Commands APIs */ +cl_int clEnqueueReadBuffer(cl_command_queue command_queue, cl_mem mem, + cl_bool blocking_read, size_t offset, size_t cb, void *ptr, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + command_queue->enqueueRead( + dynamic_cast(mem), + blocking_read, offset, cb, + ptr, std::vector(event_wait_list, + event_wait_list + num_events_in_wait_list), event); + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + return CL_OUT_OF_HOST_MEMORY; + } + + return CL_SUCCESS; +} + +cl_int clEnqueueReadBufferRect( + cl_command_queue command_queue, + cl_mem buffer, + cl_bool blocking_read, + const size_t *buffer_origin, + const size_t *host_origin, + const size_t *region, + size_t buffer_row_pitch, + size_t buffer_slice_pitch, + size_t host_row_pitch, + size_t host_slice_pitch, + void *ptr, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + assert(!"clEnqueueReadBufferRect not implemented"); + return CL_SUCCESS; +} + +cl_int clEnqueueWriteBuffer(cl_command_queue command_queue, cl_mem mem, + cl_bool blocking_write, size_t offset, size_t cb, const void * ptr, + cl_uint num_events_in_wait_list, const cl_event * event_wait_list, + cl_event * event) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + command_queue->enqueueWrite( + dynamic_cast(mem), + blocking_write, offset, cb, + ptr, std::vector(event_wait_list, + event_wait_list + num_events_in_wait_list), event); + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + /* TODO Catch bad_alloc within _cl_command_queue::enqueueWriteBuffer */ + return CL_OUT_OF_HOST_MEMORY; + } + + return CL_SUCCESS; +} + +cl_int clEnqueueWriteBufferRect( + cl_command_queue command_queue, + cl_mem buffer, + cl_bool blocking_write, + const size_t *buffer_origin, + const size_t *host_origin, + const size_t *region, + size_t buffer_row_pitch, + size_t buffer_slice_pitch, + size_t host_row_pitch, + size_t host_slice_pitch, + const void *ptr, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + assert(!"clEnqueueWriteBufferRect not implemented"); + return CL_SUCCESS; +} + +#if defined(CL_VERSION_1_2) +cl_int clEnqueueFillBuffer( + cl_command_queue command_queue, + cl_mem buffer, + const void *pattern, + size_t pattern_size, + size_t offset, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + assert(!"clEnqueueFillBuffer not implemented"); + return CL_SUCCESS; +} +#endif // #if defined(CL_VERSION_1_2) + +cl_int clEnqueueCopyBuffer(cl_command_queue command_queue, cl_mem src_buffer, + cl_mem dst_buffer, size_t src_offset, size_t dst_offset, size_t cb, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + command_queue->enqueueCopy( + dynamic_cast(src_buffer), + dynamic_cast(dst_buffer), + src_offset, dst_offset, cb, + std::vector(event_wait_list, event_wait_list + + num_events_in_wait_list), event); + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + /* TODO Catch bad_alloc within _cl_command_queue::enqueueCopy */ + return CL_OUT_OF_HOST_MEMORY; + } + + return CL_SUCCESS; +} + +cl_int clEnqueueCopyBufferRect( + cl_command_queue command_queue, + cl_mem src_buffer, + cl_mem dst_buffer, + const size_t *src_origin, + const size_t *dst_origin, + const size_t *region, + size_t src_row_pitch, + size_t src_slice_pitch, + size_t dst_row_pitch, + size_t dst_slice_pitch, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + assert(!"clEnqueueCopyBufferRect not implemented"); + return CL_SUCCESS; +} + +void * clEnqueueMapBuffer(cl_command_queue command_queue, cl_mem mem, + cl_bool blocking_map, cl_map_flags map_flags, size_t offset, size_t cb, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event, cl_int *errcode_ret) { + void *ptr = nullptr; + cl_int errcode = CL_SUCCESS; + + if (command_queue) { + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + errcode = CL_INVALID_VALUE; + } else { + try { + ptr = command_queue->enqueueMap( + dynamic_cast(mem), + blocking_map, map_flags, offset, cb, + std::vector(event_wait_list, event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + errcode = err.err(); + } + } + } else { + errcode = CL_INVALID_COMMAND_QUEUE; + } + + /* return error code */ + if (errcode_ret) { + *errcode_ret = errcode; + } + + return ptr; +} + +cl_int clEnqueueUnmapMemObject(cl_command_queue command_queue, cl_mem memobj, + void *mapped_ptr, cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, cl_event *event) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + command_queue->enqueueUnmap(memobj, mapped_ptr, + std::vector(event_wait_list, event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +#if defined(CL_VERSION_1_2) +cl_int clEnqueueMigrateMemObjects( + cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_mem_migration_flags flags, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + /* + * Validate parameters + */ + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + + if (num_mem_objects == 0 || !mem_objects) return CL_INVALID_VALUE; + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + command_queue->enqueueMigrateMemObjects( + std::vector(mem_objects, mem_objects + num_mem_objects), + flags, + std::vector(event_wait_list, event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} +#endif // #if defined(CL_VERSION_1_2) + +cl_int clEnqueueNDRangeKernel(cl_command_queue command_queue, cl_kernel kernel, + cl_uint work_dim, const size_t * global_work_offset, + const size_t * global_work_size, const size_t * local_work_size, + cl_uint num_events_in_wait_list, const cl_event * event_wait_list, + cl_event * event) { + /* + * Validate parameters + */ + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + + if (work_dim < 1 || work_dim > 3) { + return CL_INVALID_WORK_DIMENSION; + } + if (!global_work_size) return CL_INVALID_GLOBAL_WORK_SIZE; + + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + std::vector offset; + std::vector global(global_work_size, global_work_size + work_dim); + std::vector local; + + /* Convert global work offset and local work size */ + if (global_work_offset) { + offset.assign(global_work_offset, global_work_offset + work_dim); + } + if (local_work_size) { + local.assign(local_work_size, local_work_size + work_dim); + } + + command_queue->enqueueNDRangeKernel(kernel, offset, global, local, + std::vector(event_wait_list, event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + return CL_OUT_OF_HOST_MEMORY; + } + + return CL_SUCCESS; +} + +cl_int clEnqueueTask( + cl_command_queue command_queue, + cl_kernel kernel, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + /* + * Validate parameters + */ + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + try { + command_queue->enqueueTask(kernel, + std::vector(event_wait_list, event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + return err.err(); + } catch (const std::bad_alloc&) { + return CL_OUT_OF_HOST_MEMORY; + } + + return CL_SUCCESS; +} + +cl_int clEnqueueNativeKernel( + cl_command_queue command_queue, + void (*user_func)(void *), + void *args, + size_t cb_args, + cl_uint num_mem_objects, + const cl_mem *mem_list, + const void **args_mem_loc , + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + /* + * Validate parameters + */ + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + + if (!user_func) return CL_INVALID_VALUE; + if ((!args && (cb_args == 0 || num_mem_objects == 0)) + || (args && cb_args == 0)) { + return CL_INVALID_VALUE; + } + if ((num_mem_objects > 0 && (!mem_list || !args_mem_loc)) + || (num_mem_objects == 0 && (mem_list || args_mem_loc))) { + return CL_INVALID_VALUE; + } + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + /* + * Native kernels cannot be executed by remote events. As all devices in + * dOpenCL are remote, all command-queues are associated with a remote + * device such that enqueuing a native kernel always is an invalid + * operation. + */ + return CL_INVALID_OPERATION; +} + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +cl_int clEnqueueMarker(cl_command_queue command_queue, cl_event *event) { + /* Implement clEnqueueMarker using OpenCL 1.2 API */ + + /* Event must not be NULL in OpenCL 1.1 API, but may be NULL in OpenCL 1.2 + * clEnqueueMarkerWithWaitList API */ + if (!event) return CL_INVALID_VALUE; + + return clEnqueueMarkerWithWaitList(command_queue, 0, nullptr, event); +} + +cl_int clEnqueueWaitForEvents(cl_command_queue command_queue, + cl_uint num_events, const cl_event *event_list) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + if (num_events == 0 || !event_list) return CL_INVALID_VALUE; + + try { + command_queue->enqueueWaitForEvents( + std::vector(event_list, event_list + num_events)); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clEnqueueBarrier(cl_command_queue command_queue) { + /* Implement clEnqueueBarrier using OpenCL 1.2 API */ + return clEnqueueBarrierWithWaitList(command_queue, 0, nullptr, nullptr); +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +cl_int clEnqueueMarkerWithWaitList(cl_command_queue command_queue, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_EVENT_WAIT_LIST; + } + + try { + command_queue->enqueueMarker( + std::vector(event_wait_list, + event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clEnqueueBarrierWithWaitList(cl_command_queue command_queue, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event) { + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_EVENT_WAIT_LIST; + } + + try { + command_queue->enqueueBarrier( + std::vector(event_wait_list, + event_wait_list + num_events_in_wait_list), + event); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +/******************************************************************************/ + +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +/** + * @brief Returns the address of the extension function named by \c func_name. + * + * WARNING: + * This function is deprecated since OpenCL 1.2. It has been replaced by + * clGetExtensionFunctionAddressForPlatform. + * + * @param[in] func_name Name of an extension function + * @return the address of the extension function named by func_name. + */ +void * clGetExtensionFunctionAddress(const char *func_name) { + /* Implement clGetExtensionFunctionAddress using OpenCL 1.2 API */ + + /* Get extension function address for default platform dOpenCL */ + return clGetExtensionFunctionAddressForPlatform( + _cl_platform_id::dOpenCL(), func_name); +} +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +/** + * @brief Returns the address of the extension function named by \c func_name for a given platform. + * + * Use option '-Bsymbolic-functions' to make the linker (ld) bind global + * function symbols to function symbols within a shared library, if any. + * Otherwise the function pointers returned by this function may not refer + * to the dOpenCL implementations of that functions, as these may be + * overwritten, i.e. also implemented, by an ICD loader (or any other + * program) that dynamically loads dOpenCL. + * + * @param[in] platform Platform to query the extension function for + * @param[in] func_name Name of an extension function + * @return the address of the extension function named by \c func_name. + */ +void * clGetExtensionFunctionAddressForPlatform(cl_platform_id platform, + const char *func_name) { + if (!strcmp(func_name, "clCreateComputeNodeWWU")) { + return reinterpret_cast (&clCreateComputeNodeWWU); + } + if (!strcmp(func_name, "clRetainComputeNodeWWU")) { + return reinterpret_cast (&clRetainComputeNodeWWU); + } + if (!strcmp(func_name, "clReleaseComputeNodeWWU")) { + return reinterpret_cast (&clReleaseComputeNodeWWU); + } + if (!strcmp(func_name, "clGetComputeNodesWWU")) { + return reinterpret_cast (&clGetComputeNodesWWU); + } + if (!strcmp(func_name, "clGetComputeNodeInfoWWU")) { + return reinterpret_cast (&clGetComputeNodeInfoWWU); + } + + if (!strcmp(func_name, "clCreateContextFromComputeNodesWWU")) { + return reinterpret_cast (&clCreateContextFromComputeNodesWWU); + } + + if (!strcmp(func_name, "clEnqueueBroadcastBufferWWU")) { + return reinterpret_cast (&clEnqueueBroadcastBufferWWU); + } + if (!strcmp(func_name, "clEnqueueReduceBufferWWU")) { + return reinterpret_cast (&clEnqueueReduceBufferWWU); + } + + return nullptr; +} diff --git a/icdpp/src/cl_khr_icd.cpp b/icdpp/src/cl_khr_icd.cpp new file mode 100644 index 0000000..3c68674 --- /dev/null +++ b/icdpp/src/cl_khr_icd.cpp @@ -0,0 +1,262 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl_khr_icd.cpp + * + * @date 2011-02-22 + * @author Philipp Kegel + */ + +#include "cl_khr_icd.h" + +#include + +/* FIXME Link with option '-Bsymbolic-functions' */ +/* TODO Check if there are other side-effects of '-Bsymbolic-functions' */ +/** + * ICD function pointer dispatch table + * + * Use option '-Bsymbolic-functions' to make the linker (ld) bind global + * function symbols to function symbols within a shared library, if any. + * (Remember to prefix linker options with '-Wl,' when the linker is called + * indirectly via gcc, i.e. use '-Wl,-Bsymbolic-functions') + * Thus the global functions symbols within the shared library names cannot be + * overwritten by a program linked against this library. + * For example, the function pointer within the ICD function pointer dispatch + * table will be bound to the functions within this library rather than to the + * functions of an ICD loader, which provides the same global function symbols. + */ +struct _cl_icd_dispatch dispatch = { +/****************************************************************************** + * OpenCL 1.0 APIs + ******************************************************************************/ + + /* Platform APIs */ + NULL, /* clGetPlatformIDs */ + &clGetPlatformInfo, + + /* Device APIs */ + &clGetDeviceIDs, + NULL, /* clGetDeviceInfo */ + + /* Context APIs */ + NULL, /* clCreateContext */ + NULL, /* clCreateContextFromType */ + &clRetainContext, + &clReleaseContext, + &clGetContextInfo, + + /* Command Queue APIs */ + &clCreateCommandQueue, + &clRetainCommandQueue, + &clReleaseCommandQueue, + &clGetCommandQueueInfo, +#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS + &clSetCommandQueueProperty, +#else + NULL, /* clSetCommandQueueProperty (deprecated) */ +#endif /* CL_USE_DEPRECATED_OPENCL_1_0_APIS */ + + /* Memory Object APIs */ + &clCreateBuffer, +#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS + NULL, //&clCreateImage2D, + NULL, //&clCreateImage3D, +#else + NULL /* clCreateImage2D (deprecated) */, + NULL /* clCreateImage3D (deprecated) */, +#endif /* CL_USE_DEPRECATED_OPENCL_1_1_APIS */ + &clRetainMemObject, + &clReleaseMemObject, + &clGetSupportedImageFormats, + &clGetMemObjectInfo, + NULL, //&clGetImageInfo, + + /* Sampler APIs */ + NULL, //&clCreateSampler, + NULL, //&clRetainSampler, + NULL, //&clReleaseSampler, + NULL, //&clGetSamplerInfo, + + /* Program Object APIs */ + &clCreateProgramWithSource, + &clCreateProgramWithBinary, + &clRetainProgram, + &clReleaseProgram, + &clBuildProgram, + NULL /* clUnloadCompiler (not supported by ICD loader, deprecated) */, + &clGetProgramInfo, + &clGetProgramBuildInfo, + + /* Kernel Object APIs */ + &clCreateKernel, + &clCreateKernelsInProgram, + &clRetainKernel, + &clReleaseKernel, + &clSetKernelArg, + &clGetKernelInfo, + &clGetKernelWorkGroupInfo, + + /* Event Object APIs */ + &clWaitForEvents, + &clGetEventInfo, + &clRetainEvent, + &clReleaseEvent, + + /* Profiling APIs */ + &clGetEventProfilingInfo, + + /* Flush and Finish APIs */ + &clFlush, + &clFinish, + + /* Enqueued Commands APIs */ + &clEnqueueReadBuffer, + &clEnqueueWriteBuffer, + &clEnqueueCopyBuffer, + NULL, //&clEnqueueReadImage, + NULL, //&clEnqueueWriteImage, + NULL, //&clEnqueueCopyImage, + NULL, //&clEnqueueCopyImageToBuffer, + NULL, //&clEnqueueCopyBufferToImage, + &clEnqueueMapBuffer, + NULL, //&clEnqueueMapImage, + &clEnqueueUnmapMemObject, + &clEnqueueNDRangeKernel, + &clEnqueueTask, + &clEnqueueNativeKernel, +#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS + &clEnqueueMarker, + &clEnqueueWaitForEvents, + &clEnqueueBarrier, +#else + NULL /* clEnqueueMarker (deprecated) */, + NULL /* clEnqueueWaitForEvents (deprecated) */, + NULL /* clEnqueueBarrier (deprecated) */, +#endif /* CL_USE_DEPRECATED_OPENCL_1_1_APIS */ + + /* Extension function access */ +#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS + &clGetExtensionFunctionAddress, +#else + NULL, /* clGetExtensionFunctionAddress (deprecated) */ +#endif /* CL_USE_DEPRECATED_OPENCL_1_1_APIS */ + + /* OpenCL/OpenGL Sharing APIs */ + NULL, //&clCreateFromGLBuffer, +#ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS + NULL, //&clCreateFromGLTexture2D, + NULL, //&clCreateFromGLTexture3D, +#else + NULL, /* clCreateFromGLTexture2D (deprecated) */ + NULL, /* clCreateFromGLTexture3D (deprecated) */ +#endif /* CL_USE_DEPRECATED_OPENCL_1_1_APIS */ + NULL, //&clCreateFromGLRenderbuffer, + NULL, //&clGetGLObjectInfo, + NULL, //&clGetGLTextureInfo, + NULL, //&clEnqueueAcquireGLObjects, + NULL, //&clEnqueueReleaseGLObjects, + + /* OpenCL Events From OpenGL Syncs */ + NULL, //&clGetGLContextInfoKHR, + + /* Sharing With Direct3D 10 */ + NULL /* clGetDeviceIDsFromD3D10KHR */, + NULL /* clCreateFromD3D10BufferKHR */, + NULL /* clCreateFromD3D10Texture2DKHR */, + NULL /* clCreateFromD3D10Texture3DKHR */, + NULL /* clEnqueueAcquireD3D10ObjectsKHR */, + NULL /* clEnqueueReleaseD3D10ObjectsKHR */, +#if defined(CL_VERSION_1_1) + +/****************************************************************************** + * OpenCL 1.1 APIs + ******************************************************************************/ + + &clSetEventCallback, + + /* Memory Object APIs */ + &clCreateSubBuffer, + &clSetMemObjectDestructorCallback, + + /* Event Object APIs */ + &clCreateUserEvent, + &clSetUserEventStatus, + + /* Enqueued Commands APIs */ + &clEnqueueReadBufferRect, + &clEnqueueWriteBufferRect, + &clEnqueueCopyBufferRect, +#endif // #if defined(CL_VERSION_1_1) + +#if defined(CL_VERSION_1_2) +/****************************************************************************** + * OpenCL 1.2 APIs + ******************************************************************************/ + + /* Device APIs */ + &clCreateSubDevices, + &clRetainDevice, + &clReleaseDevice, + + /* Memory Object APIs */ + NULL, //&clCreateImage, + + /* Program Object APIs */ + &clCreateProgramWithBuiltInKernels, + &clCompileProgram, + &clLinkProgram, + &clUnloadPlatformCompiler, + + /* Kernel Object APIs */ + &clGetKernelArgInfo, + + /* Enqueued Commands APIs */ + &clEnqueueFillBuffer, + NULL, //&clEnqueueFillImage, + &clEnqueueMigrateMemObjects, + &clEnqueueMarkerWithWaitList, + &clEnqueueBarrierWithWaitList, + NULL, //&clSetPrintfCallback, + + /* Extension function access */ + &clGetExtensionFunctionAddressForPlatform, + + /* OpenCL/OpenGL Sharing APIs */ + NULL, //&clCreateFromGLTexture, +#endif // #if defined(CL_VERSION_1_2) +}; diff --git a/icdpp/src/cl_khr_icd.h b/icdpp/src/cl_khr_icd.h new file mode 100644 index 0000000..57d3921 --- /dev/null +++ b/icdpp/src/cl_khr_icd.h @@ -0,0 +1,852 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl_khr_icd.h + * + * @date 2011-02-22 + * @author Philipp Kegel + * + * Declaration of the ICD function pointer dispatch table which is part of the + * not publicly available ICD loader implementation. + */ + +#ifndef CLKHRICD_H_ +#define CLKHRICD_H_ + +#ifdef __APPLE__ +#include +#include +#include +//#include +#else +#include +#include +//#include +#endif + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + +struct _cl_icd_dispatch +{ +/****************************************************************************** + * OpenCL 1.0 APIs + ******************************************************************************/ + + /* Platform APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clGetPlatformIDs)( + cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetPlatformInfo)( + cl_platform_id /* platform */, + cl_platform_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Device APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDs)( + cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceInfo)( + cl_device_id /* device */, + cl_device_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Context APIs */ + CL_API_ENTRY cl_context (CL_API_CALL *clCreateContext)( + const cl_context_properties * /* properties */, + cl_uint /* num_devices */, + const cl_device_id * /* devices */, + void (CL_CALLBACK *)( /* pfn_notify */ + const char *, const void *, size_t, void *), + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_context (CL_API_CALL *clCreateContextFromType)( + const cl_context_properties * /* properties */, + cl_device_type /* device_type */, + void (CL_CALLBACK *)( /* pfn_notify*/ + const char *, const void *, size_t, void *), + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainContext)( + cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseContext)( + cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetContextInfo)( + cl_context /* context */, + cl_context_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Command Queue APIs */ + CL_API_ENTRY cl_command_queue (CL_API_CALL *clCreateCommandQueue)( + cl_context /* context */, + cl_device_id /* device */, + cl_command_queue_properties /* properties */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainCommandQueue)( + cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseCommandQueue)( + cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetCommandQueueInfo)( + cl_command_queue /* command_queue */, + cl_command_queue_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* + * WARNING: + * This API introduces mutable state into the OpenCL implementation. It has been REMOVED + * to better facilitate thread safety. The 1.0 API is not thread safe. It is not tested by the + * OpenCL 1.1 conformance test, and consequently may not work or may not work dependably. + * It is likely to be non-performant. Use of this API is not advised. Use at your own risk. + * + * Software developers previously relying on this API are instructed to set the command queue + * properties when creating the queue, instead. + */ + CL_API_ENTRY cl_int (CL_API_CALL *clSetCommandQueueProperty)( + cl_command_queue /* command_queue */, + cl_command_queue_properties /* properties */, + cl_bool /* enable */, + cl_command_queue_properties * /* old_properties */) CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED; + + /* Memory Object APIs */ + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateBuffer)( + cl_context /* context */, + cl_mem_flags /* flags */, + size_t /* size */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateImage2D)( + cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_row_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateImage3D)( + cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_depth */, + size_t /* image_row_pitch */, + size_t /* image_slice_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainMemObject)( + cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseMemObject)( + cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetSupportedImageFormats)( + cl_context /* context */, + cl_mem_flags /* flags */, + cl_mem_object_type /* image_type */, + cl_uint /* num_entries */, + cl_image_format * /* image_formats */, + cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetMemObjectInfo)( + cl_mem /* memobj */, + cl_mem_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetImageInfo)( + cl_mem /* image */, + cl_image_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Sampler APIs */ + CL_API_ENTRY cl_sampler (CL_API_CALL *clCreateSampler)( + cl_context /* context */, + cl_bool /* normalized_coords */, + cl_addressing_mode /* addressing_mode */, + cl_filter_mode /* filter_mode */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainSampler)( + cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseSampler)( + cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetSamplerInfo)( + cl_sampler /* sampler */, + cl_sampler_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Program Object APIs */ + CL_API_ENTRY cl_program (CL_API_CALL *clCreateProgramWithSource)( + cl_context /* context */, + cl_uint /* count */, + const char ** /* strings */, + const size_t * /* lengths */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_program (CL_API_CALL *clCreateProgramWithBinary)( + cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const size_t * /* lengths */, + const unsigned char ** /* binaries */, + cl_int * /* binary_status */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainProgram)( + cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseProgram)( + cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clBuildProgram)( + cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + void (CL_CALLBACK * /* pfn_notify */)( + cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clUnloadCompiler)(void) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetProgramInfo)( + cl_program /* program */, + cl_program_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetProgramBuildInfo)( + cl_program /* program */, + cl_device_id /* device */, + cl_program_build_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Kernel Object APIs */ + CL_API_ENTRY cl_kernel (CL_API_CALL *clCreateKernel)( + cl_program /* program */, + const char * /* kernel_name */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clCreateKernelsInProgram)( + cl_program /* program */, + cl_uint /* num_kernels */, + cl_kernel * /* kernels */, + cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainKernel)( + cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseKernel)( + cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clSetKernelArg)( + cl_kernel /* kernel */, + cl_uint /* arg_index */, + size_t /* arg_size */, + const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetKernelInfo)( + cl_kernel /* kernel */, + cl_kernel_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetKernelWorkGroupInfo)( + cl_kernel /* kernel */, + cl_device_id /* device */, + cl_kernel_work_group_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Event Object APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clWaitForEvents)( + cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetEventInfo)( + cl_event /* event */, + cl_event_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainEvent)( + cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseEvent)( + cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + + /* Profiling APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clGetEventProfilingInfo)( + cl_event /* event */, + cl_profiling_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + /* Flush and Finish APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clFlush)( + cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clFinish)( + cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + + /* Enqueued Commands APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReadBuffer)( + cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_read */, + size_t /* offset */, + size_t /* cb */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueWriteBuffer)( + cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_write */, + size_t /* offset */, + size_t /* cb */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueCopyBuffer)( + cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_buffer */, + size_t /* src_offset */, + size_t /* dst_offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReadImage)( + cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_read */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* row_pitch */, + size_t /* slice_pitch */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueWriteImage)( + cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_write */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* input_row_pitch */, + size_t /* input_slice_pitch */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueCopyImage)( + cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_image */, + const size_t * /* src_origin[3] */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueCopyImageToBuffer)( + cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_buffer */, + const size_t * /* src_origin[3] */, + const size_t * /* region[3] */, + size_t /* dst_offset */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueCopyBufferToImage)( + cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_image */, + size_t /* src_offset */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY void * (CL_API_CALL *clEnqueueMapBuffer)( + cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + size_t /* offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY void * (CL_API_CALL *clEnqueueMapImage)( + cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t * /* image_row_pitch */, + size_t * /* image_slice_pitch */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueUnmapMemObject)( + cl_command_queue /* command_queue */, + cl_mem /* memobj */, + void * /* mapped_ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueNDRangeKernel)( + cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* work_dim */, + const size_t * /* global_work_offset */, + const size_t * /* global_work_size */, + const size_t * /* local_work_size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueTask)( + cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueNativeKernel)( + cl_command_queue /* command_queue */, + void (*user_func)(void *), + void * /* args */, + size_t /* cb_args */, + cl_uint /* num_mem_objects */, + const cl_mem * /* mem_list */, + const void ** /* args_mem_loc */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueMarker)( + cl_command_queue /* command_queue */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueWaitForEvents)( + cl_command_queue /* command_queue */, + cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueBarrier)( + cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + + /* Extension function access */ + CL_API_ENTRY void * (CL_API_CALL *clGetExtensionFunctionAddress)( + const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0; + + /* OpenCL/OpenGL Sharing APIs */ + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromGLBuffer)( + cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLuint /* bufobj */, + int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromGLTexture2D)( + cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLenum /* target */, + cl_GLint /* miplevel */, + cl_GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromGLTexture3D)( + cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLenum /* target */, + cl_GLint /* miplevel */, + cl_GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromGLRenderbuffer)( + cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLuint /* renderbuffer */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetGLObjectInfo)( + cl_mem /* memobj */, + cl_gl_object_type * /* gl_object_type */, + cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clGetGLTextureInfo)( + cl_mem /* memobj */, + cl_gl_texture_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireGLObjects)( + cl_command_queue /* command_queue */, + cl_uint /* num_objects */, + const cl_mem * /* mem_objects */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseGLObjects)( + cl_command_queue /* command_queue */, + cl_uint /* num_objects */, + const cl_mem * /* mem_objects */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + + /* OpenCL Events From OpenGL Syncs */ + clGetGLContextInfoKHR_fn clGetGLContextInfoKHR; + + /* Sharing With Direct3D 10 */ + void * /* clGetDeviceIDsFromD3D10KHR_fn */ clGetDeviceIDsFromD3D10KHR; + void * /* clCreateFromD3D10BufferKHR_fn */ clCreateFromD3D10BufferKHR; + void * /* clCreateFromD3D10Texture2DKHR_fn */ clCreateFromD3D10Texture2DKHR; + void * /* clCreateFromD3D10Texture3DKHR_fn */ clCreateFromD3D10Texture3DKHR; + void * /* clEnqueueAcquireD3D10ObjectsKHR_fn */ clEnqueueAcquireD3D10ObjectsKHR; + void * /* clEnqueueReleaseD3D10ObjectsKHR_fn */ clEnqueueReleaseD3D10ObjectsKHR; + +#if defined(CL_VERSION_1_1) +/****************************************************************************** + * OpenCL 1.1 APIs + ******************************************************************************/ + + CL_API_ENTRY cl_int (CL_API_CALL *clSetEventCallback)( + cl_event /* event */, + cl_int /* command_exec_callback_type */, + void (CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_1; + + /* Memory Object APIs */ + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateSubBuffer)( + cl_mem /* buffer */, + cl_mem_flags /* flags */, + cl_buffer_create_type /* buffer_create_type */, + const void * /* buffer_create_info */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1; + + CL_API_ENTRY cl_int (CL_API_CALL *clSetMemObjectDestructorCallback)( + cl_mem /* memobj */, + void (CL_CALLBACK * /*pfn_notify*/)( + cl_mem /* memobj */, + void * /*user_data*/), + void * /*user_data */ ) CL_API_SUFFIX__VERSION_1_1; + + /* Event Object APIs */ + CL_API_ENTRY cl_event (CL_API_CALL *clCreateUserEvent)( + cl_context /* context */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1; + + CL_API_ENTRY cl_int (CL_API_CALL *clSetUserEventStatus)( + cl_event /* event */, + cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1; + + /* Enqueued Commands APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReadBufferRect)( + cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_read */, + const size_t * /* buffer_origin */, + const size_t * /* host_origin */, + const size_t * /* region */, + size_t /* buffer_row_pitch */, + size_t /* buffer_slice_pitch */, + size_t /* host_row_pitch */, + size_t /* host_slice_pitch */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueWriteBufferRect)( + cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_write */, + const size_t * /* buffer_origin */, + const size_t * /* host_origin */, + const size_t * /* region */, + size_t /* buffer_row_pitch */, + size_t /* buffer_slice_pitch */, + size_t /* host_row_pitch */, + size_t /* host_slice_pitch */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueCopyBufferRect)( + cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_buffer */, + const size_t * /* src_origin */, + const size_t * /* dst_origin */, + const size_t * /* region */, + size_t /* src_row_pitch */, + size_t /* src_slice_pitch */, + size_t /* dst_row_pitch */, + size_t /* dst_slice_pitch */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1; + +#endif // #if defined(CL_VERSION_1_1) +#if defined(CL_VERSION_1_2) +/****************************************************************************** + * OpenCL 1.2 APIs + ******************************************************************************/ +/* TODO Verify order of OpenCL 1.2 APIs in ICD dispatch table */ + + /* Device APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clCreateSubDevices)( + cl_device_id /* in_device */, + const cl_device_partition_property * /* properties */, + cl_uint /* num_devices */, + cl_device_id * /* out_devices */, + cl_uint * /* num_devices_ret */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clRetainDevice)( + cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clReleaseDevice)( + cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2; + + /* Memory Object APIs */ + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateImage)( + cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + const cl_image_desc * /* image_desc */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; + + /* Program Object APIs */ + CL_API_ENTRY cl_program (CL_API_CALL *clCreateProgramWithBuiltInKernels)( + cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* kernel_names */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clCompileProgram)( + cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + cl_uint /* num_input_headers */, + const cl_program * /* input_headers */, + const char ** /* header_include_names */, + void (CL_CALLBACK * /* pfn_notify */)( + cl_program /* program */, + void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_program (CL_API_CALL *clLinkProgram)( + cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + cl_uint /* num_input_programs */, + const cl_program * /* input_programs */, + void (CL_CALLBACK * /* pfn_notify */)( + cl_program /* program */, + void * /* user_data */), + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clUnloadPlatformCompiler)( + cl_platform_id /* platform */) CL_API_SUFFIX__VERSION_1_2; + + /* Kernel Object APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clGetKernelArgInfo)( + cl_kernel /* kernel */, + cl_uint /* arg_indx */, + cl_kernel_arg_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_2; + + /* Enqueued Commands APIs */ + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueFillBuffer)( + cl_command_queue /* command_queue */, + cl_mem /* buffer */, + const void * /* pattern */, + size_t /* pattern_size */, + size_t /* offset */, + size_t /* size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueFillImage)( + cl_command_queue /* command_queue */, + cl_mem /* image */, + const void * /* fill_color */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueMigrateMemObjects)( + cl_command_queue /* command_queue */, + cl_uint /* num_mem_objects */, + const cl_mem * /* mem_objects */, + cl_mem_migration_flags /* flags */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueMarkerWithWaitList)( + cl_command_queue /* command_queue */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + + CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueBarrierWithWaitList)( + cl_command_queue /* command_queue */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + + /* TODO Check if clSetPrintfCallback is an official OpenCL API or not + * While the API appeared in the early OpenCL 1.2 header it has been removed in the latest revisions. + * It has also been removed in version 1.2.4 of the C++ bindings. */ + CL_API_ENTRY cl_int (CL_API_CALL *clSetPrintfCallback)( + cl_context /* context */, + void (CL_CALLBACK * /* pfn_notify */)( + cl_context /* program */, + cl_uint /*printf_data_len */, + char * /* printf_data_ptr */, + void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_2; + + /* Extension function access */ + /* TODO Verify that clGetExtensionFunctionAddressForPlatform is + * correctly placed in ICD dispatch table */ + CL_API_ENTRY void * (CL_API_CALL *clGetExtensionFunctionAddressForPlatform)( + cl_platform_id /* platform */, + const char * /* func_name */) CL_API_SUFFIX__VERSION_1_2; + + /* OpenCL/OpenGL Sharing APIs */ + CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromGLTexture)( + cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLenum /* target */, + cl_GLint /* miplevel */, + cl_GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; + +#endif // #if defined(CL_VERSION_1_2) +}; + +#ifdef __cplusplus +} +#endif + +/******************************************************************************/ + +extern struct _cl_icd_dispatch dispatch; + +#endif /* CLKHRICD_H_ */ diff --git a/icdpp/src/cl_wwu_collective.cpp b/icdpp/src/cl_wwu_collective.cpp new file mode 100644 index 0000000..48b68c2 --- /dev/null +++ b/icdpp/src/cl_wwu_collective.cpp @@ -0,0 +1,172 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl_wwu_collective.cpp + * + * @date 2012-07-06 + * @author Philipp Kegel + * + * @brief Implementation of the OpenCL API extension specified for collective operations. + * + * Function calls of the C API are redirected to corresponding method of a C++ + * implementation. Functions in this file only perform type conversions and + * related operations, e.g. validating list parameters that are converted into + * vectors. The C++ methods validate parameters. + */ + +#include "CommandQueue.h" +#include "ComputeNode.h" +#include "Context.h" +#include "Kernel.h" +#include "Memory.h" + +#include "dclicd/Buffer.h" +#include "dclicd/Error.h" + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include + + +/* Collective operation APIs */ + +cl_int clEnqueueBroadcastBufferWWU(cl_command_queue *command_queue_list, + cl_mem src_buffer, cl_uint num_dst_buffers, cl_mem *dst_buffer_list, + size_t src_offset, const size_t *dst_offset_list, size_t cb, + cl_uint num_events_in_wait_list, const cl_event * event_wait_list, + cl_event *event) { + std::vector dsts; + std::vector dstOffsets; + + if (!command_queue_list) return CL_INVALID_VALUE; + if ((num_dst_buffers == 0) || !dst_buffer_list) { + return CL_INVALID_VALUE; + } + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + /* convert destination buffer list */ + dsts.reserve(num_dst_buffers); + for (cl_mem *i = dst_buffer_list; i != dst_buffer_list + num_dst_buffers; ++i) { + dsts.push_back(dynamic_cast(*i)); + } + + if (dst_offset_list) { + dstOffsets.assign(dst_offset_list, dst_offset_list + num_dst_buffers); + } + + try { + _cl_command_queue::enqueueBroadcast( + std::vector(command_queue_list, + command_queue_list + num_dst_buffers), + dynamic_cast(src_buffer), dsts, + src_offset, dstOffsets, cb, + std::vector(event_wait_list, event_wait_list + + num_events_in_wait_list), event); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clEnqueueReduceBufferWWU(cl_command_queue command_queue, + cl_uint num_src_buffers, cl_mem *src_buffer_list, cl_mem dst_buffer, +// const size_t *src_offset_list, size_t dst_offset, size_t cb, + cl_kernel kernel, cl_uint work_dim, const size_t * global_work_offset, + const size_t * global_work_size, const size_t * local_work_size, +// cl_reduce_operator_WWU oper, + cl_uint num_events_in_wait_list, const cl_event * event_wait_list, + cl_event *event) { + std::vector srcs; + std::vector offset; + std::vector global; + std::vector local; + + if (!command_queue) return CL_INVALID_COMMAND_QUEUE; + if ((num_src_buffers == 0) || !src_buffer_list) { + return CL_INVALID_VALUE; + } + if (work_dim < 1 || work_dim > 3) { + return CL_INVALID_WORK_DIMENSION; + } + if (!global_work_size) return CL_INVALID_GLOBAL_WORK_SIZE; + if ((num_events_in_wait_list > 0 && !event_wait_list) + || (num_events_in_wait_list == 0 && event_wait_list)) { + return CL_INVALID_VALUE; + } + + /* convert source buffer list */ + srcs.reserve(num_src_buffers); + for (cl_mem *i = src_buffer_list; i != src_buffer_list + num_src_buffers; ++i) { + srcs.push_back(dynamic_cast(*i)); + } + + /* Convert global work offset and local work size */ + if (global_work_offset) { + offset.assign(global_work_offset, global_work_offset + work_dim); + } + global.assign(global_work_size, global_work_size + work_dim); + if (local_work_size) { + local.assign(local_work_size, local_work_size + work_dim); + } + + try { + command_queue->enqueueReduce( + srcs, dynamic_cast(dst_buffer), +// std::vector(src_offset_list, src_offset_list + num_src_buffers), +// dst_offset, cb, + kernel, offset, global, local, +// oper, + std::vector(event_wait_list, event_wait_list + + num_events_in_wait_list), event); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} diff --git a/icdpp/src/cl_wwu_dcl.cpp b/icdpp/src/cl_wwu_dcl.cpp new file mode 100644 index 0000000..ae205a2 --- /dev/null +++ b/icdpp/src/cl_wwu_dcl.cpp @@ -0,0 +1,278 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file cl_wwu_dcl.cpp + * + * @date 2011-08-11 + * @author Philipp Kegel + * + * @brief Implementation of the OpenCL API extension specified for dOpenCL. + * + * Function calls of the C API are redirected to corresponding method of a C++ + * implementation. Functions in this file only perform type conversions and + * related operations, e.g. validating list parameters that are converted into + * vectors. The C++ methods validate parameters. + */ + +#include "CommandQueue.h" +#include "ComputeNode.h" +#include "Context.h" +#include "Memory.h" +#include "Platform.h" +#include "Retainable.h" + +#include "dclicd/Error.h" +#include "dclicd/utility.h" + +#include "dclicd/detail/ContextProperties.h" + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include + + +/** + * @brief Initialization routine. + */ +//void __attribute__ ((constructor)) __dclInit() { +//} + +/** + * @brief Cleans up when dOpenCL is closed or the main program exits, respectively. + */ +//void __attribute__ ((destructor)) __dclFinalize() { +//} + +/* Compute node APIs */ + +cl_compute_node_WWU clCreateComputeNodeWWU( + cl_platform_id platform, + const char *url, + void (*pfn_notify)( + cl_compute_node_WWU, cl_int, void *), + void *user_data, + cl_int *errcode_ret) { + cl_compute_node_WWU computeNode = nullptr; + cl_int errcode; + + if (platform) { + /* TODO Validate platform */ + } else { + /* Behavior is implementation defined, if platform is NULL */ + platform = _cl_platform_id::dOpenCL(); + } + + try { + computeNode = platform->createComputeNode(url, pfn_notify, user_data); + errcode = CL_SUCCESS; + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc&) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return computeNode; +} + +cl_int clRetainComputeNodeWWU( + cl_compute_node_WWU compute_node) { + if (compute_node) { + /* TODO Validate compute node */ + compute_node->retain(); + } else { + return CL_INVALID_NODE_WWU; + } + + return CL_SUCCESS; +} + +cl_int clReleaseComputeNodeWWU( + cl_compute_node_WWU compute_node) { + if (compute_node) { + /* TODO Validate compute node */ + try { + dclicd::release(compute_node); + } catch (const dclicd::Error& err) { + return err.err(); + } + } else { + return CL_INVALID_NODE_WWU; + } + + return CL_SUCCESS; +} + +cl_int clGetComputeNodesWWU(cl_platform_id platform, cl_uint num_entries, + cl_compute_node_WWU *compute_nodes, cl_uint *num_compute_nodes) { + if (platform) { + /* TODO Validate platform */ + } else { + /* Behavior is implementation defined, if platform is NULL */ + platform = _cl_platform_id::dOpenCL(); + } + + if (compute_nodes) { + if (num_entries == 0) return CL_INVALID_VALUE; + } else { + if (!num_compute_nodes) return CL_INVALID_VALUE; + } + + try { + std::vector computeNodes_; + + platform->getComputeNodes(computeNodes_); + + if (compute_nodes) { + auto computeNode = std::begin(computeNodes_); + for (cl_uint i = 0; i < num_entries && computeNode != std::end(computeNodes_); ++i) { + *compute_nodes++ = *computeNode++; + } + } + if (num_compute_nodes) *num_compute_nodes = computeNodes_.size(); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +cl_int clGetComputeNodeInfoWWU( + cl_compute_node_WWU compute_node, + cl_compute_node_info_WWU param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) { + /* TODO Validate compute node */ + if (!compute_node) return CL_INVALID_NODE_WWU; + + try { + compute_node->getInfo(param_name, param_value_size, param_value, + param_value_size_ret); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +/* Device APIs */ + +cl_int clGetDeviceIDsFromComputeNodeWWU(cl_compute_node_WWU compute_node, + cl_device_type device_type, cl_uint num_entries, cl_device_id *devices, + cl_uint *num_devices) { + /* TODO Validate compute node */ + if (!compute_node) return CL_INVALID_NODE_WWU; + + if (devices) { + if (num_entries == 0) return CL_INVALID_VALUE; + } else { + if (!num_devices) return CL_INVALID_VALUE; + } + + try { + std::vector devices_; + + compute_node->getDevices(device_type, devices_); + + if (devices) { + auto device = std::begin(devices_); + for (cl_uint i = 0; i < num_entries && device != std::end(devices_); ++i) { + *devices++ = *device++; + } + } + if (num_devices) *num_devices = devices_.size(); + } catch (const dclicd::Error& err) { + return err.err(); + } + + return CL_SUCCESS; +} + +/* Context APIs */ + +cl_context clCreateContextFromComputeNodesWWU( + const cl_context_properties *properties, cl_int num_compute_nodes, + const cl_compute_node_WWU *compute_nodes, void(*pfn_notify)( + const char *errinfo, const void *private_info, size_t cb, + void *user_data), void *user_data, cl_int *errcode_ret) { + cl_context context = nullptr; + cl_int errcode = CL_SUCCESS; + + if (num_compute_nodes == 0 || !compute_nodes) { + errcode = CL_INVALID_VALUE; + } + + /* + * Create context + */ + if (errcode == CL_SUCCESS) { + try { + std::unique_ptr properties_; + if (properties) properties_.reset(new dclicd::detail::ContextProperties(properties)); + + context = new _cl_context(properties_.get(), + std::vector(compute_nodes, + compute_nodes + num_compute_nodes), + pfn_notify, user_data); + errcode = CL_SUCCESS; + } catch (const dclicd::Error& err) { + errcode = err.err(); + } catch (const std::bad_alloc& err) { + errcode = CL_OUT_OF_HOST_MEMORY; + } + } + + if (errcode_ret) { + *errcode_ret = errcode; + } + + return context; +} diff --git a/icdpp/src/dclicd/Buffer.cpp b/icdpp/src/dclicd/Buffer.cpp new file mode 100644 index 0000000..9ddf323 --- /dev/null +++ b/icdpp/src/dclicd/Buffer.cpp @@ -0,0 +1,216 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Buffer.cpp + * + * \date 2011-08-21 + * \author Philipp Kegel + */ + +#include "Buffer.h" + +#include "../Context.h" +#include "../Device.h" +#include "../Memory.h" +#include "../Retainable.h" + +#include "Error.h" +#include "utility.h" + +#include "detail/MappedMemory.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclicd { + +Buffer::Buffer( + cl_context context, + cl_mem_flags flags, + size_t size, + void *host_ptr) : + _cl_mem(context, flags, size, host_ptr), _associatedMemory(nullptr), _offset(0) { + try { + /* + * Create buffer + */ + dclasio::message::CreateBuffer request(_id, _context->remoteId(), flags, size); + + /* Tentative solution: + * Copy data to all compute nodes of context, if CL_MEM_COPY_HOST_PTR or + * CL_MEM_USE_HOST_PTR (cached copy) is specified. + * The memory objects on the compute nodes will not be updated by the + * memory coherency protocol, as there is no synchronization point (an + * event) before the first command actually uses the memory object on + * any compute node. */ + if (flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) { + const auto& computeNodes = _context->computeNodes(); + std::vector> dataTransfers; + + /* TODO Never send data to compute nodes when creating a memory object + * The current solution is working but introduces considerable + * communication overhead as the data is sent to *all* compute nodes. + * For an efficient implementation, do not copy this data to any + * compute node before the memory object is accessed by a device on + * a compute node. However, if CL_MEM_COPY_HOST_PTR has been + * specified the data has to be copied to a local buffer (_data). */ + + // send request and data + for (auto computeNode : computeNodes) { + assert(computeNode != nullptr); + + computeNode->sendRequest(request); + auto sending = + computeNode->sendData(size, host_ptr); // copy host pointer + dataTransfers.push_back(sending); + } + + // await responses from all compute nodes + for (auto computeNode : computeNodes) { + /* TODO Await completion of data transfer + * Handle failed data transfers explicitly, as possibly no + * response will be sent in that case. */ + + computeNode->awaitResponse(request); + /* TODO Receive responses from *all* compute nodes, i.e., do not stop receipt on first failure */ + } + } else { + dcl::executeCommand(_context->computeNodes(), request); + } + + dcl::util::Logger << dcl::util::Info + << "Buffer created (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw Error(err); + } catch (const dcl::IOException& err) { + throw Error(err); + } catch (const dcl::ProtocolException& err) { + throw Error(err); + } +} + +Buffer::~Buffer() { } + +void * Buffer::map(cl_map_flags flags, size_t offset, size_t cb) { + void *ptr = nullptr; + + if (flags != CL_MAP_READ && + flags != CL_MAP_WRITE && + flags != (CL_MAP_READ | CL_MAP_WRITE)) { + // mapping flags are invalid + throw Error(CL_INVALID_VALUE); + } + if (offset + cb > _size) throw Error(CL_INVALID_VALUE); + + { + std::lock_guard lock(_dataMutex); + allocHostMemory(); + ptr = static_cast(_data) + offset; // derive ptr from cache or host_ptr + _mappedRegions.insert(std::make_pair( + ptr, detail::MappedBufferRegion(flags, offset, cb))); + } + + return ptr; +} + +void Buffer::unmap(void *mappedPtr) { + std::lock_guard lock(_dataMutex); + if (_mappedRegions.erase(mappedPtr) != 1) { + /* mappedPtr does not point to a mapped region of this memory object */ + throw Error(CL_INVALID_VALUE); + } + /* TODO Release host memory */ +// freeHostMemory(); +} + +const detail::MappedBufferRegion * Buffer::findMapping(void *mappedPtr) const { + std::lock_guard lock(_dataMutex); + + auto i = _mappedRegions.find(mappedPtr); + if (i != std::end(_mappedRegions)) { + return &i->second; + } else { // mapping not found + return nullptr; + } +} + +cl_mem_object_type Buffer::type() const { + return CL_MEM_OBJECT_BUFFER; +} + +cl_uint Buffer::mapCount() const { + std::lock_guard lock(_dataMutex); + return _mappedRegions.size(); +} + +cl_mem Buffer::associatedMemObject() const { + return nullptr; +} + +size_t Buffer::offset() const { + return 0; +} + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/Buffer.h b/icdpp/src/dclicd/Buffer.h new file mode 100644 index 0000000..de971a0 --- /dev/null +++ b/icdpp/src/dclicd/Buffer.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Buffer.h + * + * \date 2011-08-21 + * \author Philipp Kegel + */ + +#ifndef BUFFER_H_ +#define BUFFER_H_ + +#include "../Memory.h" + +#include "detail/MappedMemory.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclicd { + +class Buffer: public _cl_mem { +public: + Buffer( + cl_context context, + cl_mem_flags flags, + size_t size, + void *host_ptr); + + virtual ~Buffer(); + + /*! + * \brief Maps a region of this buffer into the host address space and returns a pointer to this mapped region. + * + * This method only allocates the pointer to the mapped region of the buffer + * but does not actually map, i.e. copy its data from a device. + * + * \param[in] flags + * \param[in] offset + * \param[in] cb + * \return a pointer to the mapped region of the buffer + */ + void * map( + cl_map_flags flags, + size_t offset, + size_t cb); + + void unmap( + void *mappedPtr); + + const detail::MappedBufferRegion * findMapping( + void *mappedPtr) const; + +protected: + cl_mem_object_type type() const ; + cl_uint mapCount() const; + cl_mem associatedMemObject() const; + size_t offset() const; + +private: + /*! + * \brief A list of mapped regions of this memory object. + * + * A pointer for a mapped region is always derived from the data cache of + * this memory object. The size of this member is the mapCount of this + * memory object. + */ + std::map _mappedRegions; + + /* + * Sub-buffer attributes + */ + cl_mem _associatedMemory; + size_t _offset; +}; + +} /* namespace dclicd */ + +#endif /* BUFFER_H_ */ diff --git a/icdpp/src/dclicd/Error.cpp b/icdpp/src/dclicd/Error.cpp new file mode 100644 index 0000000..ea21bc7 --- /dev/null +++ b/icdpp/src/dclicd/Error.cpp @@ -0,0 +1,95 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * \file Error.cpp + * + * \date 2011-02-06 + * \author Philipp Kegel + */ + +#include "Error.h" + +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +namespace dclicd { + +Error::Error(cl_int err, const char *what) throw () : + _err(err) +{ + if (what) { + /* a string must not be initialized with NULL */ + _what.assign(what); + } +} + +Error::Error(cl_int err, const std::string& what) throw () : + _err(err), _what(what) { } + +Error::Error(const dcl::CLError& err) throw() : + _err(err.err()), _what(err.what()) { } + +Error::Error(const dcl::ConnectionException& err) throw() : + _err(CL_CONNECTION_ERROR_WWU), _what(err.what()) { } + +Error::Error(const dcl::IOException& err) throw() : + _err(CL_IO_ERROR_WWU), _what(err.what()) { } + +Error::Error(const dcl::ProtocolException& err) throw() : + _err(CL_PROTOCOL_ERROR_WWU), _what(err.what()) { } + +Error::~Error() throw() { } + +const char * Error::what() const throw() { + return _what.c_str(); +} + +cl_int Error::err() const throw() { + return _err; +} + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/Error.h b/icdpp/src/dclicd/Error.h new file mode 100644 index 0000000..227a3ce --- /dev/null +++ b/icdpp/src/dclicd/Error.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * \file Error.h + * + * \date 2011-02-06 + * \author Philipp Kegel + */ + +#ifndef ERROR_H_ +#define ERROR_H_ + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclicd { + +class Error: public std::exception { +public: + Error(cl_int err, const char *what = nullptr) throw (); + Error(cl_int err, const std::string& what) throw (); + + /*! \brief Creates an OpenCL error from a dOpenCL CL error. + * + * \param err a dOpenCL CL error + */ + Error(const dcl::CLError& err) throw (); + + /*! \brief Creates an OpenCL error from a dOpenCL exception. + * + * \param err a dOpenCL exception + */ + Error(const dcl::ConnectionException& err) throw (); + Error(const dcl::IOException& err) throw (); + Error(const dcl::ProtocolException& err) throw (); + + virtual ~Error() throw (); + + /*! \brief Gets the error string associated with this exception. + * + * \return a memory pointer to the error message string. + */ + virtual const char * what() const throw (); + + /*! \brief Gets the error code associated with this exception. + * + * \return the error code + */ + cl_int err() const throw (); + +protected: + cl_int _err; + std::string _what; +}; + +} /* namespace dclicd */ + +#endif /* ERROR_H_ */ diff --git a/icdpp/src/dclicd/Event.cpp b/icdpp/src/dclicd/Event.cpp new file mode 100644 index 0000000..010128b --- /dev/null +++ b/icdpp/src/dclicd/Event.cpp @@ -0,0 +1,420 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.cpp + * + * \date 2011-06-21 + * \author Philipp Kegel + */ + +#include "Event.h" + +#include "../Context.h" +#include "../CommandQueue.h" +#include "../Memory.h" +#include "../Platform.h" +#include "../Retainable.h" + +#include "Error.h" +#include "utility.h" + +#include "command/Command.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include // abort +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclicd { + +/****************************************************************************** + * Event + ******************************************************************************/ + +Event::Event(cl_context context, + const std::shared_ptr& command, + const std::vector& memoryObjects) : + _cl_event(context, CL_QUEUED), + _command(command), _commandQueued(dcl::util::clock.getTime()), + _memoryObjects(memoryObjects) +{ + assert(command != nullptr); // command must not be NULL +#ifndef NDEBUG + /* Context must be context of command's command queue */ + command->commandQueue()->getInfo(CL_QUEUE_CONTEXT, sizeof(context), &context, nullptr); + assert(context == _context); +#endif + + /* register event (required for consistency protocol) */ + _context->getPlatform()->remote().objectRegistry().bind(_command->remoteId(), *this); + + try { + std::vector memoryObjectIds; + + for (auto memoryObject : memoryObjects) { + memoryObjectIds.push_back(memoryObject->remoteId()); + } + + dclasio::message::CreateEvent createEvent(_context->remoteId(), + _command->remoteId(), memoryObjectIds); + std::vector computeNodes(_context->computeNodes()); + + /* Create list of 'other' compute nodes. + * Other compute nodes are compute nodes where no command has been + * enqueued but which belong to the same context as the command queue + * where the associated command has been enqueued. */ + computeNodes.erase(std::find(std::begin(computeNodes), std::end(computeNodes), + &_command->commandQueue()->computeNode())); + + /* Create substitute events on other compute nodes */ + dcl::executeCommand(computeNodes, createEvent); + dcl::util::Logger << dcl::util::Info + << "Event created (ID=" << _command->remoteId() << ')' + << std::endl; + } catch (const dcl::CLError& err) { + throw Error(err); + } catch (const dcl::IOException& err) { + throw Error(err); + } catch (const dcl::ProtocolException& err) { + throw Error(err); + } + + _command->setEvent(*this); // attach event to local command + _command->commandQueue()->retain(); +} + +Event::~Event() { + dclicd::release(_command->commandQueue()); + + /* deregister event */ + _context->getPlatform()->remote().objectRegistry().unbind(remoteId()); +} + +dcl::object_id Event::remoteId() const { + return _command->remoteId(); +} + +void Event::wait() const { + /* Perform an implicit flush to ensure that the associated command will be + * executed eventually */ + _command->commandQueue()->flush(); + + /* Do not wait for the associated command's execution status but on the + * event's one as the event status also includes the completion of + * operations associated with the event, e.g., triggering the callbacks. */ + waitNoFlush(); +} + +bool Event::onCommandExecutionStatusChanged(cl_int status) { + /* TODO Send event status update to other compute nodes directly from the + * compute node hosting the original event. + * The following is a work-around for missing node-to-node communication. + * However, commands that are finished by the host, e.g., 'read buffer', + * still have to send the event status update. */ + if (status < 0 || status == CL_COMPLETE) { /* command failed or has been completed */ + std::vector computeNodes = _context->computeNodes(); + + /* + * Forward event status change to other compute nodes in context + * The event status has been set to an error code or to 'complete' on + * the compute node owning the event. The statuses of the corresponding + * substitute events on other compute nodes of the context now have to + * be updated accordingly. + */ + computeNodes.erase(std::find(std::begin(computeNodes), std::end(computeNodes), + &_command->commandQueue()->computeNode())); + if (!computeNodes.empty()) { + try { + dclasio::message::CommandExecutionStatusChangedMessage message(remoteId(), status); + + dcl::sendMessage(computeNodes, message); + dcl::util::Logger << dcl::util::Debug + << "Forwarded update of command execution status to compute nodes (ID=" << remoteId() + << ", status=" << status + << ')' << std::endl; + } catch (const dcl::DCLException& err) { + /* Application state has become inconsistent, abort */ + std::cerr << "ERROR: event status update failed" << std::endl; + abort(); + } + } + } + + return setCommandExecutionStatus(status); +} + +void Event::getProfilingInfo( + cl_kernel_info param_name, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) const { + /* + * Do NOT check locally if event is complete! + * Remote event may be complete after _cl_command_queue::finish, but local + * event still can be incomplete because of message latency + if (!isComplete()) throw Error(CL_PROFILING_INFO_NOT_AVAILABLE); + */ + + if (!_profilingInfo) { + /* Query profiling info from compute node */ + try { + dclasio::message::GetEventProfilingInfos request(remoteId()); + std::unique_ptr response( + static_cast( + _command->commandQueue()->computeNode().executeCommand( + request, dclasio::message::EventProfilingInfosReponse::TYPE).release())); + + _profilingInfo.reset(new detail::EventProfilingInfo( + response->received,response->queued, response->submit, + response->start, response->end)); + } catch (const std::bad_alloc&) { + throw Error(CL_OUT_OF_HOST_MEMORY); + } catch (const dcl::CLError& err) { + throw Error(err); + } catch (const dcl::IOException& err) { + throw Error(err); + } catch (const dcl::ProtocolException& err) { + throw Error(err); + } + } + + switch (param_name) { + case CL_PROFILING_COMMAND_QUEUED: + /* time of queuing the command on the host */ + copy_info(_commandQueued, param_value_size, param_value, + param_value_size_ret); + break; + case CL_PROFILING_COMMAND_RECEIVED_WWU: + /* time of receiving/queuing the command on the compute node */ + copy_info(_profilingInfo->received(), param_value_size, + param_value, param_value_size_ret); + break; + case CL_PROFILING_COMMAND_SUBMIT: + copy_info(_profilingInfo->submit(), param_value_size, + param_value, param_value_size_ret); + break; + case CL_PROFILING_COMMAND_START: + copy_info(_profilingInfo->start(), param_value_size, + param_value, param_value_size_ret); + break; + case CL_PROFILING_COMMAND_END: + copy_info(_profilingInfo->end(), param_value_size, + param_value, param_value_size_ret); + break; + default: + throw Error(CL_INVALID_VALUE); + } +} + +cl_command_type Event::commandType() const { + return _command->type(); +} + +cl_command_queue Event::commandQueue() const { + return _command->commandQueue(); +} + +void Event::synchronize() { + /* TODO Implement Event::synchronize + * 1. Send synchronization request to compute node + * Presumably, this step can be omitted as a synchronization request is + * implied by clWaitForEvents and clFinish, which are the only APIs (?) + * that require event synchronization on the host. + * 2. Acquire associated memory object changes */ +} + +void Event::onSynchronize(dcl::Process& process) { + dcl::util::Logger << dcl::util::Debug + << "(MEM) Event synchronization (ID=" << remoteId() + << ") requested by compute node '" << process.url() << '\'' + << std::endl; + + if (_memoryObjects.empty()) return; + + /* forward synchronization request to event's compute node */ + dclasio::message::EventSynchronizationMessage msg(remoteId()); + _command->commandQueue()->computeNode().sendMessage(msg); + dcl::util::Logger << dcl::util::Debug + << "(MEM) Forwarded event synchronization request (ID=" << remoteId() + << ") to compute node '" << _command->commandQueue()->computeNode().url() << '\'' + << std::endl; + + /* TODO Implement forwarding of acquire request in this method rather than using a memory object's mechanisms + * The acquire/release operations will be implemented on the host to + * acquire/release the associated changes of the memory objects from a + * compute node to the memory objects' host pointers. These operations must + * not interfere with synchronization operations between compute nodes that + * are currently mediated by the host (work-around for missing + * node-to-node communication). */ + + /* acquire and release memory objects from event's compute node */ + for (auto memoryObject : _memoryObjects) { + memoryObject->onAcquire(process, _command->commandQueue()->computeNode()); + } +} + +/****************************************************************************** + * User event + ******************************************************************************/ + +UserEvent::UserEvent(cl_context context) : + _cl_event(context, CL_SUBMITTED) +{ + try { + dclasio::message::CreateEvent request(context->remoteId(), _id, + std::vector()); + dcl::executeCommand(_context->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "User event created (ID=" << _id << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw Error(err); + } catch (const dcl::IOException& err) { + throw Error(err); + } catch (const dcl::ProtocolException& err) { + throw Error(err); + } + + _context->retain(); +} + +UserEvent::~UserEvent() { + dclicd::release(_context); +} + +dcl::object_id UserEvent::remoteId() const { + return _id; +} + +void UserEvent::wait() const { + /* + * User events are not associated with a command queue. Therefore, no + * command queue is flushed when waiting for a user event. + */ + waitNoFlush(); +} + +void UserEvent::setStatus(cl_int status) { + if (status > 0) { + /* Event status to set must be either CL_COMPLETE or a negative integer + * value */ + throw Error(CL_INVALID_VALUE); + } + + { + std::lock_guard lock(_statusMutex); + if (_status < 0 || _status == CL_COMPLETE) { + /* Event status has already been set */ + throw Error(CL_INVALID_OPERATION); + } + } + + /* + * Broadcast user event status update + */ + try { + dclasio::message::CommandExecutionStatusChangedMessage request(_id, status); + dcl::sendMessage(_context->computeNodes(), request); + dcl::util::Logger << dcl::util::Info + << "User event status set (ID=" << remoteId() + << ", status=" << status + << ')' << std::endl; + } catch (const dcl::CLError& err) { + throw Error(err); + } catch (const dcl::IOException& err) { + throw Error(err); + } catch (const dcl::ProtocolException& err) { + throw Error(err); + } + + setCommandExecutionStatus(status); +} + +void UserEvent::getProfilingInfo( + cl_profiling_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) const { + /* Profiling is never available for user events */ + throw Error(CL_PROFILING_INFO_NOT_AVAILABLE); +} + +cl_command_type UserEvent::commandType() const { + /* User events always are associated with a user command */ + return CL_COMMAND_USER; +} + +cl_command_queue UserEvent::commandQueue() const { + /* User events are not associated with a command queue */ + return nullptr; +} + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/Event.h b/icdpp/src/dclicd/Event.h new file mode 100644 index 0000000..f1535bf --- /dev/null +++ b/icdpp/src/dclicd/Event.h @@ -0,0 +1,228 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.h + * + * \date 2011-06-21 + * \author Philipp Kegel + */ + +#ifndef EVENT_H_ +#define EVENT_H_ + +#include "../Event.h" + +#include "detail/EventProfilingInfo.h" + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dclicd { + +namespace command { + +/* forward declarations */ +class Command; + +} /* namespace command */ + +/******************************************************************************/ + +class Event: + public _cl_event, // extends _cl_event + public dcl::SynchronizationListener { // implements SynchronizationListener +public: + /*! + * \brief Creates an event associated with a specified command. + * + * On compute nodes other than the compute node where the associated command + * has been enqueued, a substitute event is created to replace the native + * OpenCL event which resides on the compute node where the associated + * command has been enqueued. + * Internally, these substitute event are implemented as user events, but + * they hold additional information for synchronization purposes. + * + * \param[in] context the context that is associated with this event + * \param[in] command the command that this event is associated with + * \param[in] memoryObjects the memory objects associated with this event + */ + Event( + cl_context context, + const std::shared_ptr& command, + const std::vector& memoryObjects = std::vector()); + virtual ~Event(); + + dcl::object_id remoteId() const; + + /*! + * \brief Wait for the event to be completed. + * + * This method is a convenience method for _cl_event::waitForEvents. + * Unlike _cl_event::wait it performs an implicit flush on the event's + * associated command queue. + */ + void wait() const; + + /*! + * \brief Sets the event's command execution status. + * + * This method should only be called by the event's associated command to + * synchronize the event's command execution status with the actual + * execution status of its associated command + * + * \param[in] status the new command execution status + * \return \c true, if this event has been destroyed, otherwise \c false + * + * \see _cl_event::setCommandExecutionStatus + */ + bool onCommandExecutionStatusChanged( + cl_int status); + + void getProfilingInfo( + cl_profiling_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + + /*! + * \brief Synchronizes (acquires) the changes associated with this event + * + * Usually, this method is implicitly called when waiting for an event. + * However, clFinish also is a synchronization point and, therefore, + * requires the implementation to call this method. + */ + void synchronize(); + + /* + * SynchronizationListener API + * + * This method is only required to work-around the missing node-to-node + * communication. The host will never own an event which a compute node can + * synchronize with. However, the host can synchronize with a compute node's + * event. + */ + + void onSynchronize( + dcl::Process& process); + +protected: + cl_command_type commandType() const; + cl_command_queue commandQueue() const; + +private: + std::shared_ptr _command; //!< Command that is associated with this event + cl_ulong _commandQueued; //!< Queuing time of command on host + std::vector _memoryObjects; //!< Memory objects associated with this event + + mutable std::unique_ptr _profilingInfo; //!< Profiling info (optional, cached) +}; + +/******************************************************************************/ + +#if 0 +class ReadMemoryEvent : public Event { // extends Event +public: + /*! + * \brief Creates an event associated with a specified read memory object command. + * + * Unlike other events, this event is responsible for broadcasting a + * 'command complete' message to other compute nodes, as the command is + * finished on the host. + * Currently, the same is performed by Event but as a work-around for + * missing node-to-node communication. + * + * \param[in] context the context that is associated with this event + * \param[in] command the read memory command that this event is associated with + */ + ReadMemoryEvent( + cl_context context, + command::ReadMemoryCommand& command); + virtual ~Event(); + + void onCommandExecutionStatusChanged( + cl_int status); +}; +#endif + +/******************************************************************************/ + +class UserEvent: public dcl::Remote, public _cl_event { +public: + UserEvent( + cl_context context); + virtual ~UserEvent(); + + /*! + * \brief Returns this user event's remote ID + * + * This method implements _cl_event::remoteId and overwrites dcl::Remote::remoteId. + * + * \return this user event's remote ID + */ + dcl::object_id remoteId() const; + + void wait() const; + + void setStatus( + cl_int status); + + void getProfilingInfo( + cl_profiling_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) const; + +protected: + cl_command_type commandType() const; + cl_command_queue commandQueue() const; +}; + +} /* namespace dclicd */ + +#endif /* EVENT_H_ */ diff --git a/icdpp/src/dclicd/command/Command.cpp b/icdpp/src/dclicd/command/Command.cpp new file mode 100644 index 0000000..ad827a3 --- /dev/null +++ b/icdpp/src/dclicd/command/Command.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Command.cpp + * + * \date 2012-03-24 + * \author Philipp Kegel + */ + +#include "Command.h" + +#include "../../CommandQueue.h" +#include "../../Platform.h" +#include "../../Retainable.h" + +#include "../Error.h" +#include "../Event.h" + +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dclicd { + +namespace command { + +Command::Command(cl_command_type type, cl_command_queue commandQueue) : + _type(type), _commandQueue(commandQueue), + _executionStatus(CL_QUEUED), _event(nullptr) +{ + cl_context context; + + assert(commandQueue != nullptr); // command queue must not be NULL + + // listen to remote command + _commandQueue->getInfo(CL_QUEUE_CONTEXT, sizeof(context), &context, nullptr); + context->getPlatform()->remote().objectRegistry().bind(_id, *this); +} + +Command::~Command() { + cl_context context; + + _commandQueue->getInfo(CL_QUEUE_CONTEXT, sizeof(context), &context, nullptr); + context->getPlatform()->remote().objectRegistry().unbind(_id); +} + +cl_command_type Command::type() const { + return _type; +} + +cl_command_queue Command::commandQueue() const { + return _commandQueue; +} + +void Command::setEvent(Event& event) { + std::lock_guard lock(_executionStatusMutex); + + assert(_event == nullptr); // event must be set only once + + _event = &event; +#ifdef NDEBUG + _event->onCommandExecutionStatusChanged(_executionStatus); +#else + assert(!_event->onCommandExecutionStatusChanged(_executionStatus)); +#endif +} + +bool Command::isComplete() const { + std::lock_guard lock(_executionStatusMutex); + return (_executionStatus < 0 /* error */ + || _executionStatus == CL_COMPLETE); +} + +void Command::wait() const { + std::lock_guard lock(_executionStatusMutex); + while (_executionStatus != CL_COMPLETE && _executionStatus >= 0) { + _executionStatusChanged.wait(_executionStatusMutex); + } +} + +void Command::onExecutionStatusChanged(cl_int executionStatus) { +#ifndef NDEBUG + /* Ensure that command execution status only changes in the following + * manner: QUEUED -> SUBMIT -> RUNNING -> COMPLETE | */ + { + std::lock_guard lock(_executionStatusMutex); + assert(_executionStatus > 0 && executionStatus < _executionStatus); + } +#endif + + try { + if (executionStatus == CL_SUBMITTED) { + executionStatus = submit(); + } + if (executionStatus == CL_COMPLETE || executionStatus < 0) { + executionStatus = complete(executionStatus); + } + } catch (const Error& err) { + executionStatus = err.err(); + } + + { + std::lock_guard lock(_executionStatusMutex); + /* executionStatus may have been changed concurrently, e.g., by an + * operation in method submit */ + if (executionStatus < _executionStatus) { + _executionStatus = executionStatus; + dcl::util::Logger << dcl::util::Debug + << "Changed command execution status (ID=" << _id + << ", status=" << _executionStatus << ')' + << std::endl; + + if (_event) { + // update command execution status of associated event + if (_event->onCommandExecutionStatusChanged(_executionStatus)) { + /* WARNING: When the event is deleted, it releases this + * command. There must be another owner of this command to + * ensure that the command is not deleted while this method + * in executed. + * Currently, the command queue is the other owner of a + * command. Unlike the event, the command queue waits for + * the command to complete (see CommandQueue::finishLocally) + * before deleting it. As waiting for a command is + * synchronized, the command will not be deleted before this + * method has been completely executed. */ + // FIXME Ensure that event has been created with new + delete _event; + /* Do not set _event = nullptr, such that no other event can + * be attached to this command using setEvent. */ + } + } + + _executionStatusChanged.notify_all(); + } + } +} + +cl_int Command::submit() { + // no action + return CL_RUNNING; +} + +cl_int Command::complete(cl_int errcode) { + // no action + return errcode; +} + +} /* namespace command */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/command/Command.h b/icdpp/src/dclicd/command/Command.h new file mode 100644 index 0000000..71ab525 --- /dev/null +++ b/icdpp/src/dclicd/command/Command.h @@ -0,0 +1,147 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Command.h + * + * \date 2012-03-24 + * \author Philipp Kegel + */ + +#ifndef COMMAND_H_ +#define COMMAND_H_ + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclicd { + +class Event; + +/* ****************************************************************************/ + +namespace command { + +class Command: public dcl::Remote, public dcl::CommandListener { +public: + /*! + * \brief Creates a command + * + * \param[in] command_type the type of this command + * \param[in] command_queue the command queue that is associated with this command + */ + Command( + cl_command_type type, + cl_command_queue commandQueue); + virtual ~Command(); + + cl_command_type type() const; + cl_command_queue commandQueue() const; + + /*! + * \brief Attaches an event to this command. + * + * This operation must be called only once, as the event shall not be + * detached or changed. + * + * \param[in] event the event to attach to this command + */ + void setEvent( + dclicd::Event& event); + + /*! + * \brief Checks, if this command is complete + * + * \return \c true, if this command is complete, otherwise \c false + */ + bool isComplete() const; + + /*! + * \brief Wait for the command to be completed. + */ + void wait() const; + + /* + * Command listener API + */ + + void onExecutionStatusChanged( + cl_int executionStatus); + +protected: + /*! + * \brief Executes this command when its execution status changes to \c CL_SUBMITTED. + * + * \return a new execution status of the command + * The returned execution status depends on whether the host can complete + * the command directly (\c CL_COMPLETE is returned), or the command will be + * completed later (by the host or compute node, \c CL_RUNNING will be + * returned). + */ + virtual cl_int submit(); + + /*! + * \brief Finishes this command when its execution status changes to \c CL_COMPLETE or an error code + * + * \param[in] errcode return (error) code of the preceding command execution steps + * \return the commands final return code; \c CL_COMPLETE on success + */ + virtual cl_int complete( + cl_int errcode); + + cl_command_type _type; //!< Command type + cl_command_queue _commandQueue; //!< Command queue that the command has been enqueued to + cl_int _executionStatus; //!< Execution status + mutable std::recursive_mutex _executionStatusMutex; //!< Mutex for command execution status + mutable std::condition_variable_any _executionStatusChanged; //!< Condition: command execution status changed + + dclicd::Event *_event; //!< Associated event; can be \c NULL +}; + +} /* namespace command */ + +} /* namespace dclicd */ + +#endif /* COMMAND_H_ */ diff --git a/icdpp/src/dclicd/command/MappingCommand.cpp b/icdpp/src/dclicd/command/MappingCommand.cpp new file mode 100644 index 0000000..6d46cc1 --- /dev/null +++ b/icdpp/src/dclicd/command/MappingCommand.cpp @@ -0,0 +1,158 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MappingCommand.cpp + * + * \date 2012-03-24 + * \author Philipp Kegel + */ + +#include "MappingCommand.h" + +#include "../../CommandQueue.h" +#include "../../Memory.h" + +#include "../Buffer.h" +#include "../Error.h" +#include "../utility.h" + +#include "../detail/MappedMemory.h" + +#include "Command.h" + +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dclicd { + +namespace command { + +MapBufferCommand::MapBufferCommand( + cl_command_queue commandQueue, + Buffer *buffer, + cl_map_flags flags, + size_t cb, + void *ptr) : + Command(CL_COMMAND_MAP_BUFFER, commandQueue), _buffer(buffer), + _flags(flags), _cb(cb), _ptr(ptr) { + assert(_buffer != nullptr); // buffer must not be NULL + _buffer->retain(); +} + +MapBufferCommand::~MapBufferCommand() { + release(_buffer); +} + +cl_int MapBufferCommand::submit() { + if ((_flags & CL_MAP_READ)) { + /* + * The mapped buffer region has to be synchronized, i.e., it has to be + * downloaded to the mapped pointer. + */ + // start data transfer + std::shared_ptr receipt( + _commandQueue->computeNode().receiveData(_cb, _ptr)); + // register callback to complete MapBufferCommand + receipt->setCallback(std::bind( + &MapBufferCommand::onExecutionStatusChanged, this, std::placeholders::_1)); + } + + return CL_RUNNING; +} + +/* ****************************************************************************/ + +UnmapBufferCommand::UnmapBufferCommand( + cl_command_queue commandQueue, + Buffer * memobj, + cl_map_flags flags, + size_t cb, + void * ptr) : + Command(CL_COMMAND_UNMAP_MEM_OBJECT, commandQueue), _memobj(memobj), + _flags(flags), _cb(cb), _ptr(ptr) { + assert(_memobj != nullptr); // buffer must not be NULL + _memobj->retain(); +} + +UnmapBufferCommand::~UnmapBufferCommand() { + release(_memobj); +} + +cl_int UnmapBufferCommand::submit() { + if ((_flags & CL_MAP_WRITE)) { + /* + * The mapped buffer region has to be synchronized, i.e., its data has + * to be uploaded to the command queue's compute node. + */ + // start data transfer + std::shared_ptr sending( + _commandQueue->computeNode().sendData(_cb, _ptr)); + + // UnmapBufferCommand will be completed by compute node + } + + return CL_RUNNING; +} + +cl_int UnmapBufferCommand::complete( + cl_int errcode) { + if (errcode == CL_SUCCESS) { + try { + _memobj->unmap(_ptr); // release pointer to mapped memory + } catch (const dclicd::Error& err) { + return err.err(); + } + } + + return errcode; +} + +} /* namespace command */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/command/MappingCommand.h b/icdpp/src/dclicd/command/MappingCommand.h new file mode 100644 index 0000000..9dcbce7 --- /dev/null +++ b/icdpp/src/dclicd/command/MappingCommand.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MappingCommand.h + * + * \date 2012-03-24 + * \author Philipp Kegel + */ + +#ifndef MAPPINGCOMMAND_H_ +#define MAPPINGCOMMAND_H_ + +#include "Command.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclicd { + +class Buffer; + +/* ****************************************************************************/ + +namespace command { + +class MapBufferCommand: public Command { +public: + MapBufferCommand( + cl_command_queue commandQueue, + Buffer * buffer, + cl_map_flags flags, + size_t cb, + void * ptr); + virtual ~MapBufferCommand(); + +private: + cl_int submit(); + + Buffer *_buffer; + cl_map_flags _flags; + size_t _cb; + void * _ptr; +}; + +/* ****************************************************************************/ + +class UnmapBufferCommand: public Command { +public: + UnmapBufferCommand( + cl_command_queue commandQueue, + Buffer * memobj, + cl_map_flags flags, + size_t cb, + void * ptr); + virtual ~UnmapBufferCommand(); + +private: + cl_int submit(); + + cl_int complete( + cl_int errcode); + + Buffer *_memobj; + cl_map_flags _flags; + size_t _cb; + void *_ptr; +}; + +} /* namespace command */ + +} /* namespace dclicd */ + +#endif /* MAPPINGCOMMAND_H_ */ diff --git a/icdpp/src/dclicd/command/ReadWriteCommand.cpp b/icdpp/src/dclicd/command/ReadWriteCommand.cpp new file mode 100644 index 0000000..bc366a6 --- /dev/null +++ b/icdpp/src/dclicd/command/ReadWriteCommand.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ReadWriteCommand.cpp + * + * \date 2012-03-24 + * \author Philipp Kegel + */ + +#include "ReadWriteCommand.h" + +#include "../../CommandQueue.h" + +#include "Command.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include + +namespace dclicd { + +namespace command { + +ReadMemoryCommand::ReadMemoryCommand(cl_command_type type, + cl_command_queue commandQueue, size_t cb, void *ptr) : + Command(type, commandQueue), _cb(cb), _ptr(ptr) { +} + +cl_int ReadMemoryCommand::submit() { + // start data receipt + std::shared_ptr receipt( + _commandQueue->computeNode().receiveData(_cb, _ptr)); + // register callback to complete ReadMemoryCommand + receipt->setCallback(std::bind( + &ReadMemoryCommand::onExecutionStatusChanged, this, std::placeholders::_1)); + + return CL_RUNNING; +} + +/* ****************************************************************************/ + +WriteMemoryCommand::WriteMemoryCommand(cl_command_type type, + cl_command_queue commandQueue, size_t cb, const void *ptr) : + Command(type, commandQueue), _cb(cb), _ptr(ptr) { +} + +cl_int WriteMemoryCommand::submit() { + // start data sending + _commandQueue->computeNode().sendData(_cb, _ptr); + + // WriteMemoryCommand will be completed by compute node + + return CL_RUNNING; +} + +} /* namespace command */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/command/ReadWriteCommand.h b/icdpp/src/dclicd/command/ReadWriteCommand.h new file mode 100644 index 0000000..2d313df --- /dev/null +++ b/icdpp/src/dclicd/command/ReadWriteCommand.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ReadWriteCommand.h + * + * \date 2012-03-24 + * \author Philipp Kegel + */ + +#ifndef READWRITECOMMAND_H_ +#define READWRITECOMMAND_H_ + +#include "Command.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclicd { + +namespace command { + +class ReadMemoryCommand: public Command { +public: + ReadMemoryCommand( + cl_command_type type, + cl_command_queue commandQueue, + size_t cb, + void * ptr); + +private: + cl_int submit(); + + size_t _cb; + void *_ptr; +}; + +/* ****************************************************************************/ + +class WriteMemoryCommand: public Command { +public: + WriteMemoryCommand( + cl_command_type type, + cl_command_queue commandQueue, + size_t cb, + const void * ptr); + +private: + cl_int submit(); + + size_t _cb; + const void *_ptr; +}; + +} /* namespace command */ + +} /* namespace dclicd */ + +#endif /* READWRITECOMMAND_H_ */ diff --git a/icdpp/src/dclicd/command/Readme.txt b/icdpp/src/dclicd/command/Readme.txt new file mode 100644 index 0000000..42cb02d --- /dev/null +++ b/icdpp/src/dclicd/command/Readme.txt @@ -0,0 +1,16 @@ +Commands that include data transfers (read, write, map, unmap), as all commands, +are controlled by the device or compute node, respectively, that executes that +command. +The most efficient way to implement this behavior is Remote Direct Memory Access +(RDMA), which allows the compute node to access (read, write) the host's memory +without any participation from the host. + +However, in the current implementation of dOpenCL, RDMA is not supported. +Therefore, data transfers require participation from the host. Command objects +represent these data transfers, and the operations the host has to perform in +order to facilitate the corresponding data transfer. +Commands are a work-around that replaces RDMA and are only required for the +current implementation of the dOpenCL communication library, but not for dOpenCL +in general, the command classes should be provided by the dOpenCL communication +library rather than the ICD. Even if the underlying network does not support +RDMA, dOpenCL thus will provide RDMA-like API calls for data transfers. diff --git a/icdpp/src/dclicd/detail/ContextProperties.cpp b/icdpp/src/dclicd/detail/ContextProperties.cpp new file mode 100644 index 0000000..2736218 --- /dev/null +++ b/icdpp/src/dclicd/detail/ContextProperties.cpp @@ -0,0 +1,226 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ContextProperties.cpp + * + * \date 2012-08-02 + * \author Philipp Kegel + */ + +#include "ContextProperties.h" + +#include "../../Platform.h" + +#include "../Error.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +namespace dclicd { + +namespace detail { + +ContextProperties::ContextProperties( + const cl_context_properties *properties) { + init(properties, &_size, &_properties); +} + +ContextProperties::ContextProperties( + const ContextProperties& rhs) : + _size(rhs._size) +{ + /* Deep copy properties list */ + try { + _properties = new cl_context_properties[_size]; + std::copy(rhs._properties, rhs._properties + _size, + _properties); + } catch (const std::bad_alloc&) { + throw Error(CL_OUT_OF_HOST_MEMORY); + } +} + +ContextProperties::~ContextProperties() { + delete _properties; +} + +ContextProperties& ContextProperties::operator=( + ContextProperties& rhs) { + if (&rhs != this) { + delete _properties; // discard current properties + + _size = rhs._size; + _properties = rhs._properties; + + rhs._size = 0; + rhs._properties = nullptr; + } + + return *this; +} + +ContextProperties& ContextProperties::operator=( + const cl_context_properties *properties) { + size_t size; + cl_context_properties *newProperties; + + init(properties, &size, &newProperties); + delete _properties; // discard current properties + _size = size; + _properties = newProperties; + + return *this; +} + +size_t ContextProperties::size() const { + return _size; +} + +size_t ContextProperties::numProperties() const { + return _size / 2; +} + +template +T ContextProperties::property() const { + cl_context_properties *property = _properties; + auto value = static_cast(0x0); // assume default value + + while (*property) { + auto name = *property++; + + if (name == Property) { + value = reinterpret_cast(*property); + break; + } + property++; // skip property value + } + + return value; +} + +/* explicit instantiation */ +template cl_platform_id ContextProperties::property() const; + +const cl_context_properties * ContextProperties::data() const { + return _properties; +} + +void ContextProperties::init(const cl_context_properties *properties, + size_t *size_ret, cl_context_properties **properties_ret) { + size_t size = 0; + + assert(size_ret != nullptr); + assert(properties_ret != nullptr); + + if (properties) { + std::set propertyNames; + const cl_context_properties *property = properties; + + /* + * Validate property list and determine size + */ + /* Count number of properties */ + while (*property) { // property name NULL terminates list + auto name = *property++; + + if (!propertyNames.insert(name).second) { + /* property name only be specified once */ + throw Error(CL_INVALID_PROPERTY); + } + + /* Properties other than CL_CONTEXT_PLATOFRM are *not* checked as + * this should be left to the native platforms on the compute nodes + * when creating a context with these properties. */ + switch (name) { + case CL_CONTEXT_PLATFORM: + { + std::vector platforms; + + _cl_platform_id::get(platforms); + + if (std::find(std::begin(platforms), std::end(platforms), + reinterpret_cast(*property)) == std::end(platforms)) { + throw Error(CL_INVALID_PLATFORM); + } + } + break; +// case CL_CONTEXT_D3D10_DEVICE_KHR: +// assert(!"cl_khr_d3d10_sharing not supported by dOpenCL"); +// break; +// case CL_GL_CONTEXT_KHR: +// case CL_EGL_DISPLAY_KHR: +// case CL_GLX_DISPLAY_KHR: +// case CL_WGL_HDC_KHR: +// case CL_CGL_SHAREGROUP_KHR: +// assert(!"cl_khr_gl_sharing not supported by dOpenCL"); +// break; + default: + throw Error(CL_INVALID_PROPERTY); + } + + size += 2; // count name and value + ++property; // skip property value + } + + ++size; // count terminating NULL; + } else { + throw std::invalid_argument("Context properties must not be NULL"); + } + + /* Deep copy properties list */ + try { + *properties_ret = new cl_context_properties[size]; + std::copy(properties, properties + size, *properties_ret); + } catch (const std::bad_alloc&) { + throw Error(CL_OUT_OF_HOST_MEMORY); + } + + *size_ret = size; +} + +} /* namespace detail */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/detail/ContextProperties.h b/icdpp/src/dclicd/detail/ContextProperties.h new file mode 100644 index 0000000..c527d68 --- /dev/null +++ b/icdpp/src/dclicd/detail/ContextProperties.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ContextProperties.h + * + * \date 2012-08-02 + * \author Philipp Kegel + */ + +#ifndef CONTEXTPROPERTIES_H_ +#define CONTEXTPROPERTIES_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclicd { + +namespace detail { + +/*! + * \brief A wrapper for an array of context properties. + */ +class ContextProperties { +public: + ContextProperties( + const cl_context_properties *properties); + ContextProperties( + const ContextProperties& rhs); + virtual ~ContextProperties(); + + /*! + * \brief A move assignment operator for context properties. + */ + ContextProperties& operator=( + ContextProperties& rhs); + ContextProperties& operator=( + const cl_context_properties *properties); + + /*! + * \brief Returns the size of this list of context properties. + * + * The size is the number of entries including the terminating \c NULL entry. + * + * \return the size of this property list + */ + size_t size() const; + + /*! + * \brief Returns the number of properties, i.e., name-value pairs in this list of context properties. + * + * \return the number of properties + */ + size_t numProperties() const; + + template + T property() const; + + const cl_context_properties * data() const; + +private: + static void init( + const cl_context_properties *properties, + size_t * size_ret, + cl_context_properties ** properties_ret); + + size_t _size; + cl_context_properties *_properties; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* CONTEXTPROPERTIES_H_ */ diff --git a/icdpp/src/dclicd/detail/EventProfilingInfo.cpp b/icdpp/src/dclicd/detail/EventProfilingInfo.cpp new file mode 100644 index 0000000..1adbaa9 --- /dev/null +++ b/icdpp/src/dclicd/detail/EventProfilingInfo.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file EventProfilingInfo.cpp + * + * @date 2013-03-01 + * @author Philipp Kegel + */ + +#include "EventProfilingInfo.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclicd { + +namespace detail { + +EventProfilingInfo::EventProfilingInfo( + cl_ulong received, + cl_ulong queued, cl_ulong submit, cl_ulong start, cl_ulong end) : + _received(received), _submit(submit), _start(start), _end(end) { + /* + * Determine skew of compute node clock and device clock: + * we assume that the time of receiving a command on the compute node + * (CL_PROFILING_COMMAND_RECEIVED, compute node clock) is equal to the time + * of enqueuing the command on the compute node (CL_PROFILING_COMMAND_QUEUED, + * device clock). The difference of these time points (in nanoseconds) is + * considered the skew of the compute node clock and the device clock. + * + * In the current implementation, the time of sending and receipt is not + * exactly measured when sending or receiving a command, but rather when an + * event is created. However, if the host's and compute nodes' clocks are in + * sync (e.g., when using ntpd) the following invariants hold: + * - QUEUED (host) < RECEIVED (compute node), + * - RECEIVED (compute node) == QUEUED < SUBMIT < START < END (device). + */ + _clockSkew = received - queued; +} + +cl_ulong EventProfilingInfo::clockSkew() const { + return _clockSkew; +} + +cl_ulong EventProfilingInfo::received() const { + return _received; +} + +cl_ulong EventProfilingInfo::submit() const { + return _submit + _clockSkew; +} + +cl_ulong EventProfilingInfo::start() const { + return _start + _clockSkew; +} + +cl_ulong EventProfilingInfo::end() const { + return _end + _clockSkew; +} + +} /* namespace detail */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/detail/EventProfilingInfo.h b/icdpp/src/dclicd/detail/EventProfilingInfo.h new file mode 100644 index 0000000..75ebb3f --- /dev/null +++ b/icdpp/src/dclicd/detail/EventProfilingInfo.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file EventProfilingInfo.h + * + * @date 2013-03-01 + * @author Philipp Kegel + */ + +#ifndef EVENTPROFILINGINFO_H_ +#define EVENTPROFILINGINFO_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +namespace dclicd { + +namespace detail { + +class EventProfilingInfo { +public: + /** + * @brief Creates an event profiling info set. + * + * The input times are provided by two different clocks (compute node and + * device clock). Internally the skew of these clocks is computed and added + * to all values. Thus, the values returned by this event profiling info are + * adjusted to the compute node clock. + * + * @param[in] received time of receiving/enqueuing (compute node clock) on + * the compute node + * @param[in] queued time of enqueuing the command (device clock) + * @param[in] submit time of submitting the command (device clock) + * @param[in] start time of starting the command (device clock) + * @param[in] end time of finishing the command (device clock) + */ + EventProfilingInfo( + cl_ulong received, + cl_ulong queued, + cl_ulong submit, + cl_ulong start, + cl_ulong end); + + /** + * @brief Skew of the compute node clock and device clock. + * + * By subtracting this value from the times returned by this event + * profiling info, these values are adjusted to the device clock. + * + * @return the clock skew in nanoseconds + */ + cl_ulong clockSkew() const; + + cl_ulong received() const; + cl_ulong submit() const; + cl_ulong start() const; + cl_ulong end() const; + +private: + cl_ulong _clockSkew; /**< Skew of compute node clock and device clock */ + cl_ulong _received; + cl_ulong _submit; + cl_ulong _start; + cl_ulong _end; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* EVENTPROFILINGINFO_H_ */ diff --git a/icdpp/src/dclicd/detail/KernelArgument.cpp b/icdpp/src/dclicd/detail/KernelArgument.cpp new file mode 100644 index 0000000..dd475b6 --- /dev/null +++ b/icdpp/src/dclicd/detail/KernelArgument.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file KernelArgument.cpp + * + * \date 2013-10-26 + * \author Philipp Kegel + */ + +#include "KernelArgument.h" + +#include "../../Memory.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclicd { + +namespace detail { + +KernelArgument::KernelArgument( + size_t size_) : type(dcl::kernel_arg_type::MEMORY), size(size_) { } +KernelArgument::KernelArgument( + cl_mem mem) : type(dcl::kernel_arg_type::MEMORY), size(sizeof(cl_mem)) { + assert(mem != nullptr); + dcl::object_id memId = mem->remoteId(); + value.assign(sizeof(mem), &memId); +} +KernelArgument::KernelArgument(size_t size_, const void *value_) : + type(dcl::kernel_arg_type::BINARY), size(size_), value(size_, value_) { } + +} /* namespace detail */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/detail/KernelArgument.h b/icdpp/src/dclicd/detail/KernelArgument.h new file mode 100644 index 0000000..8bd05d9 --- /dev/null +++ b/icdpp/src/dclicd/detail/KernelArgument.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file KernelArgument.h + * + * \date 2013-10-26 + * \author Philipp Kegel + */ + +#ifndef KERNELARGUMENT_H_ +#define KERNELARGUMENT_H_ + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclicd { + +namespace detail { + +class KernelArgument { +public: + KernelArgument( + size_t size_); + KernelArgument( + cl_mem mem); + KernelArgument( + size_t size_, + const void *value_); + + dcl::kernel_arg_type type; + size_t size; + dcl::Binary value; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* KERNELARGUMENT_H_ */ diff --git a/icdpp/src/dclicd/detail/KernelInfo.h b/icdpp/src/dclicd/detail/KernelInfo.h new file mode 100644 index 0000000..a1be972 --- /dev/null +++ b/icdpp/src/dclicd/detail/KernelInfo.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file KernelInfo.h + * + * \date 2013-10-26 + * \author Philipp Kegel + */ + +#ifndef KERNELINFO_H_ +#define KERNELINFO_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace dclicd { + +namespace detail { + +class KernelInfo { +public: + KernelInfo( + const std::string& functionName_, + cl_uint numArgs_, + const std::string *_attributes = nullptr); + + const std::string& functionName; + cl_uint numArgs; + + /* OpenCL 1.2 kernel info */ + const std::string * const attributes; +}; + +/******************************************************************************/ + +class KernelWorkGroupInfo { +public: + KernelWorkGroupInfo( + size_t workGroupSize_, + const size_t compileworkGroupSize_[], + cl_ulong localMemSize_, + size_t preferredWorkGroupSizeMultiple_, + cl_ulong privateMemSize_, + const size_t globalWorkSize_[] = nullptr); + +private: + size_t workGroupSize; + const size_t *compileworkGroupSize; + cl_ulong localMemSize; + size_t preferredWorkGroupSizeMultiple; + cl_ulong privateMemSize; + + /* OpenCL 1.2 kernel work-group info */ + const size_t *globalWorkSize; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* KERNELINFO_H_ */ diff --git a/icdpp/src/dclicd/detail/MappedMemory.h b/icdpp/src/dclicd/detail/MappedMemory.h new file mode 100644 index 0000000..a93907a --- /dev/null +++ b/icdpp/src/dclicd/detail/MappedMemory.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MappedMemory.h + * + * \date 2012-08-04 + * \author Philipp Kegel + */ + +#ifndef MAPPEDMEMORY_H_ +#define MAPPEDMEMORY_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclicd { + +namespace detail { + +/*! + * \brief A mapped region of a memory object. + * + * This class save information about mapped regions of memory objects, such as + * the map flags. The map flags are required, to determine whether + * synchronization of a memory object is required when the mapped region is + * unmapped. + */ +class MappedMemory { +public: + MappedMemory( + cl_map_flags map_flags) : + _map_flags(map_flags) { } + virtual ~MappedMemory() { } + + cl_map_flags flags() const { + return _map_flags; + } + +protected: + cl_map_flags _map_flags; +}; + +/******************************************************************************/ + +/*! + * \brief A mapped region of a buffer. + */ +class MappedBufferRegion : public MappedMemory { +public: + MappedBufferRegion( + cl_map_flags map_flags, + size_t offset, + size_t cb) : + MappedMemory(map_flags), _offset(offset), _cb(cb) { } + + size_t offset() const { + return _offset; + } + + size_t cb() const { + return _cb; + } + +private: + size_t _offset; + size_t _cb; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* MAPPEDMEMORY_H_ */ diff --git a/icdpp/src/dclicd/detail/ProgramBuild.cpp b/icdpp/src/dclicd/detail/ProgramBuild.cpp new file mode 100644 index 0000000..a9efb78 --- /dev/null +++ b/icdpp/src/dclicd/detail/ProgramBuild.cpp @@ -0,0 +1,255 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProgramBuild.cpp + * + * \date 2012-08-04 + * \author Philipp Kegel + */ + +#include "ProgramBuild.h" + +#include "../../Context.h" +#include "../../Device.h" +#include "../../Platform.h" +#include "../../Program.h" + +#include "../Error.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dclicd { + +namespace detail { + +ProgramBuild::ProgramBuild( + cl_program program, + const std::vector& devices, + const char *options, + void (*pfn_notify)(cl_program, void *), + void *user_data) : + _program(program), _devices(devices), _options(options ? options : ""), + _pfnNotify(pfn_notify), _userData(user_data), _buildStatus(CL_BUILD_NONE) +{ + assert(program != nullptr); // constructor is only called internally + assert(!devices.empty()); // program must be build for at least one device + if (pfn_notify == nullptr && user_data != nullptr) { + throw Error(CL_INVALID_VALUE); + } + + /* register build *before* sending request; + * otherwise a build completion message might be lost */ + _program->context()->getPlatform()->remote().objectRegistry().bind(_id, *this); + + submit(); + + /* TODO Trigger callback asynchronously */ + if (_buildStatus == CL_BUILD_SUCCESS && _pfnNotify) { + _pfnNotify(_program, _userData); + } +} + +ProgramBuild::~ProgramBuild() { + /* Deregister program build */ + _program->context()->getPlatform()->remote().objectRegistry().unbind(_id); +} + +bool ProgramBuild::isComplete() const { + std::lock_guard lock(_buildStatusMutex); + return testComplete(); +} + +bool ProgramBuild::hasFailed() const { + std::lock_guard lock(_buildStatusMutex); + return _buildStatus == CL_BUILD_PROGRAM_FAILURE; +} + +void ProgramBuild::wait() { + std::lock_guard lock(_buildStatusMutex); + while (!testComplete()) { + _buildCompleted.wait(_buildStatusMutex); + } +} + +void ProgramBuild::onComplete( + const std::vector& devices, + const std::vector& buildStatus) { + assert(devices.size() == buildStatus.size() && "Number of devices and build status do not match"); + + /* TODO Update build status and save build info (status and options) for + * devices of completed (!) build operation + for (unsigned int i = 0; i < devices->size(); ++i) { + _program->onBuildStatusChanged(devices[i], buildStatus[i], _options); + } + */ + /* TODO Set _buildStatus = CL_BUILD_SUCCESS, when all computes nodes finished building the program */ + + { + std::lock_guard lock(_buildStatusMutex); + if (testComplete()) { + /* Trigger callback if all compute nodes reported completion of program + * build */ + if (_pfnNotify) { + _pfnNotify(_program, _userData); + } + } + _buildCompleted.notify_all(); + } +} + +void ProgramBuild::submit() { + std::map> nodeDeviceIds; + + /* + * Create compute nodes' lists of device IDs + */ + for (auto device : _devices) { + assert(device != nullptr); // devices must not be NULL + nodeDeviceIds[&device->remote().getComputeNode()].push_back(device->remote().getId()); + } + + { + std::lock_guard lock(_buildStatusMutex); + std::vector> requests; + cl_int err = CL_SUCCESS; // assume successful command submission + + /* + * Create and send requests + */ + for (auto i : nodeDeviceIds) { + auto computeNode = i.first; + /* TODO Avoid copying 'build program' requests */ + dclasio::message::BuildProgram request(_program->remoteId(), i.second, _options, _id); + + /* Send requests to *all* compute nodes, i.e. do not stop on failure */ + try { + computeNode->sendRequest(request); + requests.push_back(std::make_pair(computeNode, request)); // save pending request + } catch (const dcl::IOException&) { + err = CL_IO_ERROR_WWU; + } catch (const dcl::ProtocolException&) { + err = CL_PROTOCOL_ERROR_WWU; + } + } + if (requests.empty()) { + /* no compute node will build the program; the program build failed */ + assert(err != CL_SUCCESS && "Invalid program build"); + _buildStatus = CL_BUILD_PROGRAM_FAILURE; + _buildCompleted.notify_all(); + throw dclicd::Error(err); + } + + /* + * Await responses from all compute nodes + * Also await responses if request failed on some compute nodes. + */ + for (auto i : requests) { + auto computeNode = i.first; + cl_int nodeErr = CL_SUCCESS; // assume successful response from compute node + + /* Receive responses from *all* compute nodes, i.e. do not stop on failure */ + try { + computeNode->awaitResponse(i.second); + _computeNodes.push_back(computeNode); // compute node is now building program + + /* TODO Update build info (status and options) for devices on compute node + for (auto device : devices) { + _program->onBuildStatusChanged(device, CL_BUILD_IN_PROGRESS, _options)); + } + */ + } catch (const dcl::CLError& err) { + nodeErr = err.err(); + } catch (const dcl::IOException&) { + nodeErr = CL_IO_ERROR_WWU; + } catch (const dcl::ProtocolException&) { + nodeErr = CL_PROTOCOL_ERROR_WWU; + } + + if (nodeErr != CL_SUCCESS && err == CL_SUCCESS) { + err = nodeErr; // return error from first failure + } + } + if (err != CL_SUCCESS) { // program build has not been submitted to all compute nodes + /* FIXME Program build did not fail completely, i.e., is is *not finished* yet */ +// _buildStatus = CL_BUILD_PROGRAM_FAILURE; + } + /* TODO Implement asynchronous program build */ +// _buildStatus = CL_BUILD_IN_PROGRESS; + _buildStatus = CL_BUILD_SUCCESS; + + dcl::util::Logger << dcl::util::Info + << "Program build submitted (program ID=" << _program->remoteId() + << ", build ID=" << _id + << ')' << std::endl; + } +} + +bool ProgramBuild::testComplete() const { + return (_buildStatus == CL_BUILD_SUCCESS || + _buildStatus == CL_BUILD_PROGRAM_FAILURE); +} + +} /* namespace detail */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/detail/ProgramBuild.h b/icdpp/src/dclicd/detail/ProgramBuild.h new file mode 100644 index 0000000..3ab1186 --- /dev/null +++ b/icdpp/src/dclicd/detail/ProgramBuild.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file ProgramBuild.h + * + * \date 2012-08-04 + * \author Philipp Kegel + */ + +#ifndef PROGRAMBUILD_H_ +#define PROGRAMBUILD_H_ + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +namespace dclicd { + +namespace detail { + +/*! + * \brief A pending program build operation. + */ +class ProgramBuild: + public dcl::ProgramBuildListener, // implemented ProgramBuildListener + public dcl::Remote { // extends Remote +public: + /*! + * \brief A program build operation. + */ + ProgramBuild( + cl_program program, + const std::vector& devices, + const char * options, + void (* pfn_notify)( + cl_program, void *), + void * user_data); + virtual ~ProgramBuild(); + + template + bool includesAnyDeviceOf(ForwardIterator first, ForwardIterator last) const { + return (std::find_first_of(std::begin(_devices), std::end(_devices), + first, last) != std::end(_devices)); + } + + /*! + * \brief Test if this program build is complete. + * + * \return \c true if this program build is complete, otherwise \c false + */ + bool isComplete() const; + + /*! + * \brief Test if there was a failure to build the program. + * + * \return \c true if this program build failed, otherwise \c false + */ + bool hasFailed() const; + + /*! + * \brief Awaits completion of this program build. + */ + void wait(); + + /* + * Program build listener API + */ + void onComplete( + const std::vector& devices, + const std::vector& buildStatus); + +private: + /*! + * \brief Submits the program build to the target devices' compute nodes + */ + void submit(); + + /*! + * \brief Test if this program build is complete. + * + * Unlike isComplete, this method is not thread-safe and is reserved for + * internal use. + * + * \return \c true if this program build is complete, otherwise \c false + */ + bool testComplete() const; + + std::vector _computeNodes; //!< compute nodes executing this program build + + cl_program _program; //!< Program associated with this program build + std::vector _devices; //!< Devices associated with this program build + std::string _options; + void (*_pfnNotify)(cl_program, void *); + void *_userData; + + cl_build_status _buildStatus; //!< Status of this program build (aggregated status of all devices) + mutable std::mutex _buildStatusMutex; + mutable std::condition_variable_any _buildCompleted; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* PROGRAMBUILD_H_ */ diff --git a/icdpp/src/dclicd/detail/ProgramBuildInfo.cpp b/icdpp/src/dclicd/detail/ProgramBuildInfo.cpp new file mode 100644 index 0000000..38a7a5b --- /dev/null +++ b/icdpp/src/dclicd/detail/ProgramBuildInfo.cpp @@ -0,0 +1,54 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file ProgramBuildInfo.cpp + * + * @date 2013-10-26 + * @author Philipp Kegel + */ + +#include "ProgramBuildInfo.h" + +namespace dclicd { + +namespace detail { + +ProgramBuildInfo::ProgramBuildInfo() : status(CL_BUILD_NONE) { } + +} /* namespace detail */ + +} /* namespace dclicd */ diff --git a/icdpp/src/dclicd/detail/ProgramBuildInfo.h b/icdpp/src/dclicd/detail/ProgramBuildInfo.h new file mode 100644 index 0000000..955f88f --- /dev/null +++ b/icdpp/src/dclicd/detail/ProgramBuildInfo.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file ProgramBuildInfo.h + * + * @date 2013-10-26 + * @author Philipp Kegel + */ + +#ifndef PROGRAMBUILDINFO_H_ +#define PROGRAMBUILDINFO_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +namespace dclicd { + +namespace detail { + +/** + * @brief Build info of a program for a single device. + * By default, the build status is CL_BUILD_NONE and the build options are empty. + */ +class ProgramBuildInfo { +public: + ProgramBuildInfo(); + + cl_build_status status; + std::string options; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* PROGRAMBUILDINFO_H_ */ diff --git a/icdpp/src/dclicd/detail/Retainable.h b/icdpp/src/dclicd/detail/Retainable.h new file mode 100644 index 0000000..3b74740 --- /dev/null +++ b/icdpp/src/dclicd/detail/Retainable.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/** + * @file Retainable.h + * + * @date 2013-10-26 + * @author Philipp Kegel + */ + +#ifndef RETAINABLE_H_ +#define RETAINABLE_H_ + +#include + +namespace dclicd { + +namespace detail { + +/** + * @brief A class to performs implicit reference counting to alleviate handling of shared objects + * + * This class should probably be based on boost::intrusive_ptr. + * + * !!! This class is currently not used !!! + */ +template +class Retainable { + Retainable() : _object(nullptr) { + } + + Retainable(T *object) : _object(object) { + /* FIXME Never(!) call a virtual function within a constructor */ +// validate(); + retain(); + } + + Retainable(const Retainable& rhs) : _object(rhs._object) { + retain(); + } + + virtual ~Retainable() { + if (_object == nullptr) return; + release(); + } + + Retainable& operator=(const Retainable& rhs) { + if (_object != rhs._object) { + release(); + _object = rhs._object; + retain(); + } + + return *this; + } + + operator T *() { + retain(); + return _object; + } + + void retain() { + if (_object == nullptr) return; + ++_object->ref_count; + } + + void release() { + if (_object == nullptr) return; + assert(_object->ref_count > 0); + if (--_object->ref_count == 0) { + destroy(); + delete _object; + } + } + +protected: + virtual void destroy() = 0; + + T *_object; +}; + +} /* namespace detail */ + +} /* namespace dclicd */ + +#endif /* RETAINABLE_H_ */ diff --git a/icdpp/src/dclicd/utility.cpp b/icdpp/src/dclicd/utility.cpp new file mode 100644 index 0000000..50f36c8 --- /dev/null +++ b/icdpp/src/dclicd/utility.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file utility.cpp + * + * \date 2012-02-28 + * \author Philipp Kegel + */ + +#include "utility.h" + +#include "../ComputeNode.h" + +#include "Error.h" +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dclicd { + +void copy_info(size_t size, const void *value, size_t param_value_size, + void *param_value, size_t *param_value_size_ret) { + if (param_value) { + if (size > param_value_size) { + throw Error(CL_INVALID_VALUE); + } + + /* copy parameter value */ + memcpy(param_value, value, size); + } + + if (param_value_size_ret) { + *param_value_size_ret = size; + } +} + +template<> +void copy_info( + const std::string& param, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) { + /* For strings, value_size is string length plus 1 for trailing \0 character. */ + copy_info(param.length() + 1, static_cast(param.c_str()), + param_value_size, param_value, param_value_size_ret); +} + +template<> +void copy_info( + const dcl::Binary& param, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) { + copy_info(param.size(), param.value(), param_value_size, param_value, + param_value_size_ret); +} + +/******************************************************************************/ + +template<> +void release(cl_compute_node_WWU compute_node) { + assert(compute_node != nullptr); + compute_node->release(); +} + +} /* namespace dclicd */ + diff --git a/icdpp/src/dclicd/utility.h b/icdpp/src/dclicd/utility.h new file mode 100644 index 0000000..cc79df5 --- /dev/null +++ b/icdpp/src/dclicd/utility.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file utility.h + * + * \date 2012-02-28 + * \author Philipp Kegel + */ + +#ifndef UTILITY_H_ +#define UTILITY_H_ + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include + +namespace dclicd { + +/*! + * \brief Copy information at source pointer to destination pointer. + * + * This function implements the most generic approach for copying information. + * It should be avoided in favor of the templated typed versions of copy_info. + * + * \param[in] size size of source + * \param[in] value source + * \param[in] param_value_size size of destination + * \param[out] param_value destination + * \param[out] param_value_ret size of source + */ +void copy_info( + size_t size, + const void *value, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret); + +template +void copy_info( + const T& param, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) { + copy_info(sizeof(T), static_cast(¶m), + param_value_size, param_value, param_value_size_ret); +} + +template +void copy_info( + const std::vector& param, + size_t param_value_size, + void *param_value, + size_t *param_value_size_ret) { + copy_info(sizeof(T) * param.size(), + static_cast(param.data()), param_value_size, + param_value, param_value_size_ret); +} + +template<> +void copy_info( + const std::string& param, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret); + +template<> +void copy_info( + const dcl::Binary& param, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret); + + +/******************************************************************************/ + +/** + * @brief Releases and possibly deletes a retainable object. + * + * The object must have been created using operator new. + * + * @param[in] object the object to release. object must not be NULL. + */ +template +void release(T *object) { + assert(object != nullptr); // caller should return appropriate CL_INVALID_... error code + /* FIXME Ensure that object has been created with new */ + if (object->release()) delete object; +} + +/* + * Compute nodes are deleted in _cl_platform::destroyComputeNode, such that + * there must not be a redundant delete in dclicd::release. + */ +template<> +void release(cl_compute_node_WWU compute_node); + +} /* namespace dclicd */ + +#endif /* UTILITY_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..bb5ca45 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 2.6) + +project(dOpenCLtest) + +set(DOPENCL_INCLUDE_DIR "${dOpenCLlib_SOURCE_DIR}/include" CACHE PATH "Path to dOpenCL headers") +set(DOPENCL_LIBRARY_DIR "${dOpenCLlib_BINARY_DIR}" CACHE PATH "Path to dOpenCL library") +set(DOPENCL_ICD_DIR "${dOpenCLicd_BINARY_DIR}" CACHE PATH "Path to dOpenCL ICD") + +# search for Boost.Threads +find_package(Boost 1.41.0 COMPONENTS unit_test_framework REQUIRED) + +include_directories(${DOPENCL_INCLUDE_DIR} + ${Boost_INCLUDE_DIRS}) + +link_directories(${DOPENCL_ICD_DIR} + ${DOPENCL_LIBRARY_DIR} + ${Boost_LIBRARY_DIRS}) + +# generate dOpenCL node file +file(WRITE ${PROJECT_BINARY_DIR}/dcl.nodes + "localhost") + +# +# dOpenCL test targets +# +# enable_testing() must be defined in the root CMakeLists.txt, otherwise 'make +# test' will not work correctly + +set(UTILITY_SOURCES ${PROJECT_SOURCE_DIR}/src/utility.cpp) + +add_executable(CommandQueue ${UTILITY_SOURCES} ${PROJECT_SOURCE_DIR}/src/CommandQueue.cpp) +add_executable(Context ${UTILITY_SOURCES} ${PROJECT_SOURCE_DIR}/src/Context.cpp) +add_executable(Device ${UTILITY_SOURCES} ${PROJECT_SOURCE_DIR}/src/Device.cpp) +add_executable(Event ${UTILITY_SOURCES} ${PROJECT_SOURCE_DIR}/src/Event.cpp) +add_executable(Memory + ${UTILITY_SOURCES} + ${PROJECT_SOURCE_DIR}/src/Buffer.cpp + ${PROJECT_SOURCE_DIR}/src/Mapping.cpp + ${PROJECT_SOURCE_DIR}/src/Memory.cpp + ${PROJECT_SOURCE_DIR}/src/MemoryConsistency.cpp) +add_executable(Platform ${PROJECT_SOURCE_DIR}/src/Platform.cpp) +add_executable(Program ${UTILITY_SOURCES} ${PROJECT_SOURCE_DIR}/src/Program.cpp) + +foreach(test CommandQueue Context Device Event Memory Platform Program) + add_test(${test} ${test}) + + target_link_libraries(${test} + dOpenCL + dcl + ${Boost_LIBRARIES}) + + set_property(TARGET ${test} + APPEND PROPERTY COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK) +endforeach(test) diff --git a/test/include/boost/test/parameterized_test_ex.hpp b/test/include/boost/test/parameterized_test_ex.hpp new file mode 100644 index 0000000..fc897eb --- /dev/null +++ b/test/include/boost/test/parameterized_test_ex.hpp @@ -0,0 +1,45 @@ +/*! + * \file parameterized_test_ex.hpp + * + * This file provides two additional test case macro BOOST_FIXTURE_PARAM_TEST_CASE + * and BOOST_AUTO_PARAM_TEST_CASE which extend parameterized test cases by + * fixtures and automatic registration. + * + * \date 2011-11-13 + * \author Omnifarious + * + * \url http://stackoverflow.com/questions/8084038/is-it-possible-to-use-boost-param-test-case-with-automatic-registration-on-boost + */ + +#ifndef PARAMETERIZED_TEST_EX_HPP_ +#define PARAMETERIZED_TEST_EX_HPP_ + +#include +#include +#include + +#define BOOST_FIXTURE_PARAM_TEST_CASE( test_name, F, mbegin, mend ) \ +struct test_name : public F { \ + typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \ + void test_method(const param_t &); \ +}; \ + \ +void BOOST_AUTO_TC_INVOKER( test_name )(const test_name::param_t ¶m) \ +{ \ + test_name t; \ + t.test_method(param); \ +} \ + \ +BOOST_AUTO_TU_REGISTRAR( test_name )( \ + boost::unit_test::make_test_case( \ + &BOOST_AUTO_TC_INVOKER( test_name ), #test_name, \ + (mbegin), (mend))); \ + \ +void test_name::test_method(const param_t ¶m) \ + +#define BOOST_AUTO_PARAM_TEST_CASE( test_name, mbegin, mend ) \ + BOOST_FIXTURE_PARAM_TEST_CASE( test_name, \ + BOOST_AUTO_TEST_CASE_FIXTURE, \ + mbegin, mend) + +#endif /* PARAMETERIZED_TEST_EX_HPP_ */ diff --git a/test/src/Buffer.cpp b/test/src/Buffer.cpp new file mode 100644 index 0000000..b6246dd --- /dev/null +++ b/test/src/Buffer.cpp @@ -0,0 +1,134 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Buffer.cpp + * + * Buffer test suite (part of the memory test module) + * + * \date 2013-04-07 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +#include +#include + +namespace { + +struct Context { + cl_context context; + cl_command_queue commandQueue; + + Context() { + cl_platform_id platform = dcltest::getPlatform(); + cl_device_id device = dcltest::getDevice(platform); + + context = dcltest::createContext(1, &device); + commandQueue = dcltest::createCommandQueue(context, device); + + BOOST_TEST_MESSAGE("Set up fixture"); + } + + ~Context() { + // clean up + clReleaseCommandQueue(commandQueue); + clReleaseContext(context); + + BOOST_TEST_MESSAGE("Teared down fixture"); + } +}; + +} // anonymous namespace + +/* ****************************************************************************/ + +BOOST_FIXTURE_TEST_SUITE( Buffer, Context ) + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( CreateBuffer ) +{ + const size_t SIZE = 1024; + cl_int err = CL_SUCCESS; + + // create buffer + cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, SIZE, nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // clean up + clReleaseMemObject(buffer); +} + +BOOST_AUTO_TEST_CASE( CreateBufferCopyHostPtr ) +{ + const size_t VEC_SIZE = 1024 * 1024; + std::vector vec1(VEC_SIZE, 0), vec2(VEC_SIZE, 1); + cl_int err = CL_SUCCESS; + + dcltest::fillVector(vec1, 1, 1); // initialize input data + + // create buffer from first host pointer + cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, VEC_SIZE * sizeof(cl_int), &vec1.front(), &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // download buffer to second host pointer + err = clEnqueueReadBuffer( + commandQueue, + buffer, + CL_TRUE, + 0, VEC_SIZE * sizeof(cl_int), &vec2.front(), + 0, nullptr, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + BOOST_CHECK_MESSAGE(vec1 == vec2, "Input and output buffers differ"); // compare input and output data + + // clean up + clReleaseMemObject(buffer); +} + +BOOST_AUTO_TEST_SUITE_END() // Buffer test suite diff --git a/test/src/CommandQueue.cpp b/test/src/CommandQueue.cpp new file mode 100644 index 0000000..ce2ad6a --- /dev/null +++ b/test/src/CommandQueue.cpp @@ -0,0 +1,199 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Command queue.cpp + * + * Command queue test suite + * + * \date 2013-02-18 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#define BOOST_TEST_MODULE Command queue +#include + +namespace { + +struct Context { + Context() { + cl_platform_id platform = dcltest::getPlatform(); + + device = dcltest::getDevice(platform); + context = dcltest::createContext(1, &device); + + BOOST_TEST_MESSAGE("Set up fixture"); + } + + ~Context() { + // clean up + clReleaseContext(context); + + BOOST_TEST_MESSAGE("Teared down fixture"); + } + + cl_device_id device; + cl_context context; +}; + +/* ****************************************************************************/ + +template +struct CommandQueueInfo; + +#define CommandQueueInfo(param, type) \ +template<> struct CommandQueueInfo { \ + typedef type Type; \ + static const char Name[]; }; \ +const char CommandQueueInfo::Name[] = #param; + +CommandQueueInfo(CL_QUEUE_CONTEXT, cl_context); +CommandQueueInfo(CL_QUEUE_DEVICE, cl_device_id); +CommandQueueInfo(CL_QUEUE_PROPERTIES, cl_command_queue_properties); +CommandQueueInfo(CL_QUEUE_REFERENCE_COUNT, cl_uint); + +template +void checkCommandQueueInfo(cl_command_queue command_queue, + const typename CommandQueueInfo::Type param_value) { + typename CommandQueueInfo::Type value; + size_t size; + + cl_int err = clGetCommandQueueInfo(command_queue, Param, + sizeof(typename CommandQueueInfo::Type), &value, &size); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(value, param_value); + BOOST_CHECK_EQUAL(size, sizeof(typename CommandQueueInfo::Type)); +} + +} // anonymous namespace + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_FIXTURE_TEST_CASE( CreateCommandQueue, Context ) +{ + cl_int err = CL_SUCCESS; + + cl_command_queue command_queue = clCreateCommandQueue(context, device, 0, &err); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK(command_queue != nullptr); + + // clean up + clReleaseCommandQueue(command_queue); +} + +// TODO Create a test case for each info item +BOOST_FIXTURE_TEST_CASE( GetCommandQueueInfo, Context ) +{ + cl_command_queue command_queue = dcltest::createCommandQueue(context, device); + + // validate command queue infos + checkCommandQueueInfo(command_queue, context); + checkCommandQueueInfo(command_queue, device); + checkCommandQueueInfo(command_queue, 0); + checkCommandQueueInfo(command_queue, 1); + + // clean up + clReleaseCommandQueue(command_queue); +} + +BOOST_FIXTURE_TEST_CASE( RetainCommandQueue, Context ) +{ + cl_command_queue command_queue = dcltest::createCommandQueue(context, device); + cl_uint ref_count = 0; + cl_int err = CL_SUCCESS; + + // check preconditions + err = clGetCommandQueueInfo(command_queue, CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_EQUAL(ref_count, 1); + + // validate retain command + err = clRetainCommandQueue(command_queue); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + + err = clGetCommandQueueInfo(command_queue, CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(ref_count, 2); + + // clean up + clReleaseCommandQueue(command_queue); + clReleaseCommandQueue(command_queue); +} + +BOOST_FIXTURE_TEST_CASE( ReleaseCommandQueue, Context ) +{ + cl_command_queue command_queue = dcltest::createCommandQueue(context, device); + cl_uint ref_count = 0; + cl_int err = CL_SUCCESS; + + // check preconditions + err = clRetainCommandQueue(command_queue); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clGetCommandQueueInfo(command_queue, CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_EQUAL(ref_count, 2); + + // validate release command + err = clReleaseCommandQueue(command_queue); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + err = clGetCommandQueueInfo(command_queue, CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(ref_count, 1); + + /* TODO Release should invalidate command queue when reference count becomes zero + err = clReleaseCommandQueue(command_queue); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + err = clReleaseCommandQueue(command_queue); + BOOST_CHECK_EQUAL(err, CL_INVALID_COMMAND_QUEUE); + err = clRetainCommandQueue(command_queue); + BOOST_CHECK_EQUAL(err, CL_INVALID_COMMAND_QUEUE); + err = clGetCommandQueueInfo(command_queue, CL_QUEUE_REFERENCE_COUNT, sizeof(cl_uint), &ref_count, nullptr); + BOOST_CHECK_EQUAL(err, CL_INVALID_COMMAND_QUEUE); + */ + + // clean up + clReleaseCommandQueue(command_queue); +} diff --git a/test/src/Context.cpp b/test/src/Context.cpp new file mode 100644 index 0000000..1c2db9d --- /dev/null +++ b/test/src/Context.cpp @@ -0,0 +1,147 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Buffer.cpp + * + * Context test suite + * + * \date 2013-04-07 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#define BOOST_TEST_MODULE Context +#include + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( CreateContext ) +{ + cl_platform_id platform = dcltest::getPlatform(); + cl_device_id device = nullptr; + cl_context context = nullptr; + cl_int err = CL_SUCCESS; + + context = clCreateContext(0, 1, 0, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + context = clCreateContext(0, 0, &device, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + context = clCreateContext(0, 1, &device, 0, &err, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + + dcltest::getDevices(platform, CL_DEVICE_TYPE_ALL, 1, &device); + + // create context + context = clCreateContext(0, 1, &device, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // clean up + clReleaseContext(context); +} + +BOOST_AUTO_TEST_CASE( CreateContextFromComputeNode ) +{ + cl_platform_id platform = dcltest::getPlatform(); + cl_compute_node_WWU compute_node = nullptr; + cl_context context = nullptr; + cl_int err = CL_SUCCESS; + + context = clCreateContextFromComputeNodesWWU(0, 1, 0, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + context = clCreateContextFromComputeNodesWWU(0, 0, &compute_node, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + context = clCreateContextFromComputeNodesWWU(0, 0, &compute_node, 0, &err, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + + dcltest::getComputeNodes(platform, 1, &compute_node); + + // create context from compute node + context = clCreateContextFromComputeNodesWWU(0, 1, &compute_node, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // verify context + cl_uint num_devices = 0; + cl_uint num_devices_ctx = 0; + + err = clGetDeviceIDsFromComputeNodeWWU(compute_node, CL_DEVICE_TYPE_ALL, 0, 0, &num_devices); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(num_devices), &num_devices_ctx, 0); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_EQUAL(num_devices_ctx, num_devices); + + cl_device_id devices[num_devices]; + cl_device_id devices_ctx[num_devices_ctx]; + + err = clGetDeviceIDsFromComputeNodeWWU(compute_node, CL_DEVICE_TYPE_ALL, num_devices, devices, 0); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices), &devices_ctx, 0); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + for (int i = 0; i < num_devices; ++i) { + BOOST_REQUIRE_EQUAL(devices_ctx[i], devices[i]); + } + + // clean up + clReleaseContext(context); +} + +BOOST_AUTO_TEST_CASE( CreateContextFromType ) +{ + cl_platform_id platform = dcltest::getPlatform(); + cl_context context = nullptr; + cl_int err = CL_SUCCESS; + + context = clCreateContextFromType(0, CL_DEVICE_TYPE_ALL, 0, &err, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_VALUE); + + // create context from type + context = clCreateContextFromType(0, CL_DEVICE_TYPE_ALL, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // clean up + clReleaseContext(context); +} diff --git a/test/src/Device.cpp b/test/src/Device.cpp new file mode 100644 index 0000000..2cdd749 --- /dev/null +++ b/test/src/Device.cpp @@ -0,0 +1,133 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Device.cpp + * + * Device test suite + * + * \date 2013-12-15 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#define BOOST_TEST_MODULE Device +#include + +#include +#include + +namespace { + +template +struct DeviceInfo; + +#define DeviceInfo(param, type) \ +template<> struct DeviceInfo { \ + typedef type Type; \ + static const char Name[]; }; \ +const char DeviceInfo::Name[] = #param; + +DeviceInfo(CL_DEVICE_PLATFORM, cl_platform_id); +DeviceInfo(CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities); +#ifdef CL_VERSION_1_2 +DeviceInfo(CL_DEVICE_REFERENCE_COUNT, cl_uint); +#endif + +template +void checkDeviceInfo(cl_device_id device, + const typename DeviceInfo::Type param_value) { + typename DeviceInfo::Type value; + size_t size; + + cl_int err = clGetDeviceInfo(device, Param, + sizeof(typename DeviceInfo::Type), &value, &size); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(value, param_value); + BOOST_CHECK_EQUAL(size, sizeof(typename DeviceInfo::Type)); +} + +} // anonymous namespace + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( GetDeviceIDs ) +{ + cl_platform_id platform = dcltest::getPlatform(); + cl_uint num_devices = 0; + cl_device_id device = nullptr; + cl_int err = CL_SUCCESS; + + /* TODO Test CL_INVALID_PLATFORM */ + + // test CL_INVALID_VALUE + err = clGetDeviceIDs(nullptr, CL_DEVICE_TYPE_ALL, 0, nullptr, nullptr); + BOOST_CHECK_EQUAL(err, CL_INVALID_VALUE); // devices or num_device must not both be NULL + err = clGetDeviceIDs(nullptr, CL_DEVICE_TYPE_ALL, 0, &device, &num_devices); + BOOST_CHECK_EQUAL(err, CL_INVALID_VALUE); // devices must be NULL if num_entries is 0 + + /* TODO Test getting devices */ +} + +// TODO Create a test case for each info item +BOOST_AUTO_TEST_CASE( GetDeviceInfo ) +{ + cl_platform_id platform = dcltest::getPlatform(); + cl_device_id device = dcltest::getDevice(platform); + cl_device_exec_capabilities exec_capabilities = 0; + size_t size_ret = 0; + cl_int err = CL_SUCCESS; + + checkDeviceInfo(device, platform); + + err = clGetDeviceInfo(device, CL_DEVICE_EXECUTION_CAPABILITIES, + sizeof(cl_device_exec_capabilities), &exec_capabilities, &size_ret); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(exec_capabilities & CL_EXEC_NATIVE_KERNEL, 0); + BOOST_CHECK_EQUAL(size_ret, sizeof(cl_device_exec_capabilities)); +#ifdef CL_VERSION_1_2 + checkDeviceInfo(device, 1); +#endif +} diff --git a/test/src/Event.cpp b/test/src/Event.cpp new file mode 100644 index 0000000..fda078e --- /dev/null +++ b/test/src/Event.cpp @@ -0,0 +1,240 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Event.cpp + * + * Event test suite + * + * \date 2013-02-18 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#define BOOST_TEST_MODULE Event +#include + +#include +#include +#include + +namespace { + +void eventCallback(cl_event event, cl_int execution_status, + void *user_data) { + std::cout << "Called event callback with status " << execution_status + << std::endl; +} + +/* ****************************************************************************/ + +struct Context { + Context() { + cl_platform_id platform = dcltest::getPlatform(); + cl_device_id device = dcltest::getDevice(platform); + + context = dcltest::createContext(1, &device); + commandQueue = dcltest::createCommandQueue(context, device); + + BOOST_TEST_MESSAGE("Set up fixture"); + } + + ~Context() { + // clean up + clReleaseCommandQueue(commandQueue); + clReleaseContext(context); + + BOOST_TEST_MESSAGE("Teared down fixture"); + } + + cl_context context; + cl_command_queue commandQueue; +}; + +/* ****************************************************************************/ + +template +struct EventInfo; + +#define EventInfo(param, type) \ +template<> struct EventInfo { \ + typedef type Type; \ + static const char Name[]; }; \ +const char EventInfo::Name[] = #param; + +EventInfo(CL_EVENT_CONTEXT, cl_context); +EventInfo(CL_EVENT_COMMAND_QUEUE, cl_command_queue); +EventInfo(CL_EVENT_COMMAND_TYPE, cl_uint); +EventInfo(CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int); + +template +void checkEventInfo(cl_event event, const typename EventInfo::Type param_value) { + typename EventInfo::Type value; + size_t size; + + cl_int err = clGetEventInfo(event, Param, + sizeof(typename EventInfo::Type), &value, &size); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(value, param_value); + BOOST_CHECK_EQUAL(size, sizeof(typename EventInfo::Type)); +} + +} // anonymous namespace + +/* ****************************************************************************/ + +BOOST_FIXTURE_TEST_SUITE( UserEvent, Context ) + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( CreateUserEvent ) +{ + cl_event event = nullptr; + cl_int err = CL_SUCCESS; + + event = clCreateUserEvent(nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_INVALID_CONTEXT); + + event = clCreateUserEvent(context, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // clean up + clSetUserEventStatus(event, CL_COMPLETE); // event status must be CL_COMPLETE to release the event + clReleaseEvent(event); +} + +// TODO Create a test case for each info item +BOOST_AUTO_TEST_CASE( GetUserEventInfo ) +{ + cl_context event_context = nullptr; + cl_command_queue event_queue = nullptr; + cl_command_type command_type = 0u; + size_t size = 0; + cl_int execution_status; + cl_int err = CL_SUCCESS; + + cl_event event = clCreateUserEvent(context, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // validate user event infos + checkEventInfo(event, context); + checkEventInfo(event, nullptr); + checkEventInfo(event, CL_COMMAND_USER); + checkEventInfo(event, CL_SUBMITTED); + + // clean up + clSetUserEventStatus(event, CL_COMPLETE); // event status must be CL_COMPLETE to release the event + clReleaseEvent(event); +} + +BOOST_AUTO_TEST_CASE( SetUserEventStatus ) +{ + cl_int execution_status = CL_SUBMITTED; + cl_int err = CL_SUCCESS; + + cl_event event = clCreateUserEvent(context, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + err = clSetUserEventStatus(event, CL_COMPLETE); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, + sizeof(cl_int), &execution_status, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(execution_status, CL_COMPLETE); + + // clean up + clReleaseEvent(event); +} + +BOOST_AUTO_TEST_CASE( Callback ) +{ + const size_t SIZE = 1024; + std::vector vec(SIZE, 0); + cl_event start = nullptr; + cl_event upload = nullptr; + cl_int err = CL_SUCCESS; + + // create buffer + cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, SIZE * sizeof(cl_int), nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // create user event + start = clCreateUserEvent(context, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // upload data to device + err = clEnqueueWriteBuffer( + commandQueue, + buffer, + CL_FALSE, + 0, SIZE * sizeof(cl_int), &vec.front(), + 1, &start, &upload); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + /* register event callbacks */ + err = clSetEventCallback(start, CL_COMPLETE, &eventCallback, nullptr); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + err = clSetEventCallback(upload, CL_COMPLETE, &eventCallback, nullptr); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + + // start upload + err = clSetUserEventStatus(start, CL_COMPLETE); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + err = clFlush(commandQueue); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + +// sleep(2); + + // finish command queue + err = clFinish(commandQueue); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + + // clean up + clReleaseEvent(start); + clReleaseEvent(upload); + clReleaseMemObject(buffer); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/src/Mapping.cpp b/test/src/Mapping.cpp new file mode 100644 index 0000000..b017e8c --- /dev/null +++ b/test/src/Mapping.cpp @@ -0,0 +1,166 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Mapping.cpp + * + * Memory mapping test suite (part of the memory test module) + * + * \date 2014-01-11 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +#include +#include +#include + +namespace { + +struct Context { + cl_context context; + cl_command_queue commandQueue; + cl_mem buffer; + size_t vecSize; + size_t cb; + + Context() : + vecSize(1024 * 1024) /* #vector elements */, + cb(vecSize * sizeof(cl_int)) /* buffer size */ + { + cl_platform_id platform = dcltest::getPlatform(); + cl_device_id device = dcltest::getDevice(platform); + + context = dcltest::createContext(1, &device); + commandQueue = dcltest::createCommandQueue(context, device); + buffer = dcltest::createRWBuffer(context, cb); + + BOOST_TEST_MESSAGE("Set up fixture"); + } + + ~Context() { + // clean up + clReleaseMemObject(buffer); + clReleaseCommandQueue(commandQueue); + clReleaseContext(context); + + BOOST_TEST_MESSAGE("Teared down fixture"); + } +}; + +} // anonymous namespace + +/* ****************************************************************************/ + +BOOST_FIXTURE_TEST_SUITE( Mapping, Context ) + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( MapWrite ) +{ + cl_event unmap = nullptr; + std::vector vecIn(vecSize, 0), vecOut(vecSize, 1); + cl_int err = CL_SUCCESS; + + dcltest::fillVector(vecIn, 1, 1); // initialize input data + + // map buffer + void *ptr = clEnqueueMapBuffer( + commandQueue, buffer, CL_TRUE, CL_MAP_WRITE, 0, cb, 0, nullptr, nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + memcpy(ptr, &vecIn.front(), cb); // copy data + + // unmap buffer, i.e., upload data to device + err = clEnqueueUnmapMemObject(commandQueue, buffer, ptr, 0, nullptr, &unmap); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // download data from device on second compute node + err = clEnqueueReadBuffer(commandQueue, buffer, CL_TRUE, 0, cb, + &vecOut.front(), 1, &unmap, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + BOOST_CHECK_MESSAGE(vecIn == vecOut, "Input and output buffers differ"); // compare input and output data + + // clean up + clReleaseEvent(unmap); +} + + +BOOST_AUTO_TEST_CASE( MapRead ) +{ + cl_event unmap = nullptr; + std::vector vec(vecSize, 0); + cl_int err = CL_SUCCESS; + + dcltest::fillVector(vec, 1, 1); // initialize input data + + // update data to device + err = clEnqueueWriteBuffer(commandQueue, buffer, CL_FALSE, 0, cb, + &vec.front(), 0, nullptr, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // map buffer for reading (implicit download) + void *ptr = clEnqueueMapBuffer( + commandQueue, buffer, CL_TRUE, CL_MAP_READ, 0, cb, 0, nullptr, nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // compare buffer data and mapped data + BOOST_CHECK_MESSAGE(memcmp(&vec.front(), ptr, cb) == 0, "Input data and mapped data differ"); + + // unmap buffer + err = clEnqueueUnmapMemObject(commandQueue, buffer, ptr, 0, nullptr, &unmap); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clFinish(commandQueue); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // clean up + clReleaseEvent(unmap); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/src/Memory.cpp b/test/src/Memory.cpp new file mode 100644 index 0000000..d2347b1 --- /dev/null +++ b/test/src/Memory.cpp @@ -0,0 +1,49 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Memory.cpp + * + * Memory test module + * + * \date 2013-12-17 + * \author Philipp Kegel + */ + +#define BOOST_TEST_MODULE Memory +#include + +// Currently, the master test suite of the memory test module is empty diff --git a/test/src/MemoryConsistency.cpp b/test/src/MemoryConsistency.cpp new file mode 100644 index 0000000..818e8bc --- /dev/null +++ b/test/src/MemoryConsistency.cpp @@ -0,0 +1,223 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file MemoryConsistency.cpp + * + * Memory consistency test suite (part of the memory test module) + * + * \date 2013-02-18 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +#include +#include + +namespace { + +struct MultiDeviceContext { + MultiDeviceContext() : + vecSize(1024 * 1024) /* #vector elements */, + cb(vecSize * sizeof(cl_int)) /* buffer size */ + { + cl_platform_id platform = dcltest::getPlatform(); + cl_compute_node_WWU nodes[2]; + + dcltest::getComputeNodes(platform, 2, nodes); + devices[0] = dcltest::getDevice(nodes[0]); + devices[1] = dcltest::getDevice(nodes[1]); + + context = dcltest::createContext(2, devices); + commandQueues[0] = dcltest::createCommandQueue(context, devices[0]); + commandQueues[1] = dcltest::createCommandQueue(context, devices[1]); + buffer = dcltest::createRWBuffer(context, cb); + + BOOST_TEST_MESSAGE("Setup fixture"); + } + + ~MultiDeviceContext() { + // clean up + clReleaseMemObject(buffer); + clReleaseCommandQueue(commandQueues[0]); + clReleaseCommandQueue(commandQueues[1]); + clReleaseContext(context); + + BOOST_TEST_MESSAGE("Teared down fixture"); + } + + cl_device_id devices[2]; + cl_command_queue commandQueues[2]; + cl_context context; + cl_mem buffer; + size_t vecSize; + size_t cb; +}; + +} // anonymous namespace + +/* ****************************************************************************/ + +BOOST_FIXTURE_TEST_SUITE( MemoryConsistency, MultiDeviceContext ) + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( WriteRead ) +{ + cl_event write = nullptr; + std::vector vecIn(vecSize, 0), vecOut(vecSize, 1); + cl_int err = CL_SUCCESS; + + dcltest::fillVector(vecIn, 1, 1); // initialize input data + + // upload data to device on first compute node + err = clEnqueueWriteBuffer(commandQueues[0], buffer, CL_FALSE, 0, cb, + &vecIn.front(), 0, nullptr, &write); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // ensure start of data upload to first compute node + err = clFlush(commandQueues[0]); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // download data from device on second compute node + err = clEnqueueReadBuffer(commandQueues[1], buffer, CL_TRUE, 0, cb, + &vecOut.front(), 1, &write, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + BOOST_CHECK_MESSAGE(vecIn == vecOut, "Input and output buffers differ"); // compare input and output data + + // clean up + clReleaseEvent(write); +} + +BOOST_AUTO_TEST_CASE( NDRangeKernelRead ) +{ + const char *source = "\ +__kernel void init(__global int *v) { \ + v[get_global_id(0)] = get_global_id(0); \ +}"; + cl_event init = nullptr; + std::vector hVec(vecSize, 0), dVec(vecSize, 1); + cl_int err = CL_SUCCESS; + + dcltest::fillVector(hVec, 0, 1); // initialize host vector + + cl_program program = clCreateProgramWithSource(context, 1, &source, nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clBuildProgram(program, 2, devices, nullptr, nullptr, nullptr); + cl_kernel kernel = clCreateKernel(program, "init", &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // submit kernel to device on first compute node + err = clEnqueueNDRangeKernel(commandQueues[0], kernel, + 1, nullptr, &vecSize, nullptr, 0, nullptr, &init); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // ensure start of kernel execution on first compute node + err = clFlush(commandQueues[0]); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // download data from device on second compute node + err = clEnqueueReadBuffer(commandQueues[1], buffer, CL_TRUE, 0, cb, + &dVec.front(), 1, &init, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + BOOST_CHECK_MESSAGE(hVec == dVec, "Host and device buffers differ"); // compare host and device buffer + + // clean up + clReleaseEvent(init); + clReleaseKernel(kernel); + clReleaseProgram(program); +} + +/*! + * \brief Test cross-over exchange of two memory objects + */ +BOOST_AUTO_TEST_CASE( ConcurrentWriteRead ) +{ + cl_event write[2] = {nullptr, nullptr}; + cl_event read[2] = {nullptr, nullptr}; + std::vector vecIn0(vecSize, 1), vecIn1(vecSize, 2); + std::vector vecOut0(vecSize, 0), vecOut1(vecSize, 0); + cl_int err = CL_SUCCESS; + + cl_mem buffer1 = dcltest::createRWBuffer(context, cb); + + // upload data to device on first compute node + err = clEnqueueWriteBuffer(commandQueues[0], buffer, CL_FALSE, 0, cb, + &vecIn0.front(), 0, nullptr, &write[0]); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // upload data to device on second compute node + err = clEnqueueWriteBuffer(commandQueues[1], buffer1, CL_FALSE, 0, cb, + &vecIn1.front(), 0, nullptr, &write[1]); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // download data from device on first compute node + err = clEnqueueReadBuffer(commandQueues[0], buffer1, CL_FALSE, 0, cb, + &vecOut0.front(), 1, &write[1], &read[0]); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + // download data from device on second compute node/ + err = clEnqueueReadBuffer(commandQueues[1], buffer, CL_FALSE, 0, cb, + &vecOut1.front(), 1, &write[0], &read[1]); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + // await completion of data transfers/ + err = clWaitForEvents(2, read); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + + BOOST_CHECK_MESSAGE(vecIn0 == vecOut1, "Input and output buffers differ"); // compare input and output data + BOOST_CHECK_MESSAGE(vecIn1 == vecOut0, "Input and output buffers differ"); // compare input and output data + + // clean up + clReleaseEvent(write[0]); + clReleaseEvent(write[1]); + clReleaseEvent(read[0]); + clReleaseEvent(read[1]); + clReleaseMemObject(buffer1); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/src/Platform.cpp b/test/src/Platform.cpp new file mode 100644 index 0000000..85ed578 --- /dev/null +++ b/test/src/Platform.cpp @@ -0,0 +1,122 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Platform.cpp + * + * Platform test suite + * + * \date 2013-02-19 + * \author Philipp Kegel + */ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#define BOOST_TEST_MODULE Platform +#include + +#include +#include + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_AUTO_TEST_CASE( GetPlatformIDs ) +{ + cl_platform_id platform[] = {nullptr, nullptr}; + cl_uint num_platforms = 0; + cl_int err = CL_SUCCESS; + + err = clGetPlatformIDs(1, nullptr, nullptr); + BOOST_CHECK_EQUAL(err, CL_INVALID_VALUE); + + err = clGetPlatformIDs(0, platform, nullptr); + BOOST_CHECK_EQUAL(err, CL_INVALID_VALUE); + + err = clGetPlatformIDs(0, nullptr, &num_platforms); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + // there should be only one platform available + BOOST_CHECK_EQUAL(num_platforms, 1); + + err = clGetPlatformIDs(1, platform, &num_platforms); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + // one and only one platform (dOpenCL) should be returned + BOOST_CHECK_MESSAGE(platform[0] != nullptr, "clGetPlatformIDs must return a platform"); + BOOST_CHECK_MESSAGE(platform[1] == nullptr, "clGetPlatformIDs must not return more than one platform"); + BOOST_CHECK_EQUAL(num_platforms, 1); +} + +#define checkPlatformInfo(platform, param_name, param_value) \ +{ \ + size_t size = 0; \ + char value[1024]; /* FIXME does not work for info values larger than 1k */ \ + cl_int err = clGetPlatformInfo((platform), (param_name), sizeof(value), value, &size); \ + BOOST_CHECK_EQUAL(err, CL_SUCCESS); \ + BOOST_CHECK_MESSAGE(strcmp(value, (param_value)) == 0, #param_name " is not '" param_value "'"); \ + BOOST_CHECK_EQUAL(size, strlen(param_value) + 1); /* size includes terminating zero */ \ +} + +// TODO Create a test case for each info item +BOOST_AUTO_TEST_CASE( GetPlatformInfo ) +{ + cl_platform_id platform = nullptr; + cl_int err = CL_SUCCESS; + + // obtain platform + err = clGetPlatformIDs(1, &platform, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(platform != nullptr); // one and only one platform (dOpenCL) should be returned + + /* TODO test error code for invalid platform */ + + err = clGetPlatformInfo(platform, 0, 0, nullptr, nullptr); + BOOST_CHECK_EQUAL(err, CL_INVALID_VALUE); // invalid parameter name should not be accepted + + // use platform 'dOpenCL', if no platform is specified + checkPlatformInfo(nullptr, CL_PLATFORM_NAME, "dOpenCL"); + + // check parameter return values + checkPlatformInfo(platform, CL_PLATFORM_NAME, "dOpenCL"); + checkPlatformInfo(platform, CL_PLATFORM_VENDOR, "University of Muenster"); + checkPlatformInfo(platform, CL_PLATFORM_PROFILE, "FULL_PROFILE"); + checkPlatformInfo(platform, CL_PLATFORM_VERSION, "OpenCL 1.1"); + checkPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, "cl_wwu_dcl cl_wwu_collective"); +} diff --git a/test/src/Program.cpp b/test/src/Program.cpp new file mode 100644 index 0000000..ecc7718 --- /dev/null +++ b/test/src/Program.cpp @@ -0,0 +1,187 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file Program.cpp + * + * Program test suite + * + * \date 2013-12-13 + * \author Philipp Kegel + */ + +#include "utility.h" + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#define BOOST_TEST_MODULE Program +#include + +#include +#include + +namespace { + +struct Context { + Context() { + cl_platform_id platform = dcltest::getPlatform(); + + device = dcltest::getDevice(platform); + context = dcltest::createContext(1, &device); + + BOOST_TEST_MESSAGE("Set up fixture"); + } + + ~Context() { + // clean up + clReleaseContext(context); + + BOOST_TEST_MESSAGE("Teared down fixture"); + } + + cl_device_id device; + cl_context context; +}; + +/* ****************************************************************************/ + +template +struct ProgramInfo; + +#define ProgramInfo(param, type) \ +template<> struct ProgramInfo { \ + typedef type Type; \ + static const char Name[]; }; \ +const char ProgramInfo::Name[] = #param; + +ProgramInfo(CL_PROGRAM_CONTEXT, cl_context); +ProgramInfo(CL_PROGRAM_NUM_DEVICES, cl_uint); +ProgramInfo(CL_PROGRAM_DEVICES, cl_device_id *); +ProgramInfo(CL_PROGRAM_SOURCE, char *); +ProgramInfo(CL_PROGRAM_BINARIES, unsigned char **); +ProgramInfo(CL_PROGRAM_BINARY_SIZES, size_t *); +ProgramInfo(CL_PROGRAM_REFERENCE_COUNT, cl_uint); +#ifdef CL_VERSION_1_2 +ProgramInfo(CL_PROGRAM_NUM_KERNELS, cl_uint); +ProgramInfo(CL_PROGRAM_KERNEL_NAMES, char *); +#endif + +template +void checkProgramInfo(cl_program program, + const typename ProgramInfo::Type param_value) { + typename ProgramInfo::Type value; + size_t size; + + // FIXME Allocate memory for pointer-based values + cl_int err = clGetProgramInfo(program, Param, + sizeof(typename ProgramInfo::Type), &value, &size); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(value, param_value); + BOOST_CHECK_EQUAL(size, sizeof(typename ProgramInfo::Type)); +} + +} // anonymous namespace + +/* **************************************************************************** + * Test cases + ******************************************************************************/ + +BOOST_FIXTURE_TEST_CASE( CreateProgramWithSource, Context ) +{ + cl_int err = CL_SUCCESS; + cl_uint num_sources = 3u; + const char *sources[] = {dcltest::source, dcltest::source1, dcltest::source2}; + size_t lengths[] = {strlen(dcltest::source), strlen(dcltest::source1), strlen(dcltest::source2)}; + + cl_program program = clCreateProgramWithSource(context, num_sources, sources, lengths, &err); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK(program != nullptr); + + // clean up + clReleaseProgram(program); +} + +/* TODO Test clCreateProgramWithBinary */ + +// TODO Create a test case for each info item +BOOST_FIXTURE_TEST_CASE( GetProgramInfo, Context ) +{ + cl_program program = dcltest::createProgramWithSource(context, 1, &dcltest::source); + cl_uint num_devices = 0; + std::unique_ptr devices; + cl_int err = CL_SUCCESS; + + // get device list from context + err = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &num_devices, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_GE(num_devices, 1); + devices.reset(new cl_device_id[num_devices]); + err = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(devices.get()), devices.get(), nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + for (cl_uint i = 0; i < num_devices; ++i) { + BOOST_REQUIRE(devices[i] != nullptr); + } + + // validate program infos/ + checkProgramInfo(program, context); + checkProgramInfo(program, num_devices); + checkProgramInfo(program, 1); + + // check program devices + cl_device_id devices_ret[num_devices]; + size_t size_ret; + err = clGetProgramInfo(program, CL_PROGRAM_DEVICES, + sizeof(cl_device_id) * num_devices, &devices_ret, &size_ret); + BOOST_CHECK_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_EQUAL(devices_ret[0], device); + BOOST_CHECK_EQUAL(size_ret, sizeof(cl_device_id) * num_devices); + + // TODO Check program source + // TODO Check program binaries + // TODO Check binary sizes +#ifdef CL_VERSION_1_2 + /* TODO Check CL_PROGRAM_NUM_KERNELS, CL_PROGRAM_KERNEL_NAMES (must fail) */ +#endif + + // clean up + clReleaseProgram(program); +} diff --git a/test/src/utility.cpp b/test/src/utility.cpp new file mode 100644 index 0000000..1c1bebd --- /dev/null +++ b/test/src/utility.cpp @@ -0,0 +1,197 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file utility.cpp + * + * \date 2013-12-08 + * \author Philipp Kegel + */ + +#include + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include +#include + +namespace dcltest { + +const char *source = + "__kernel void add(__global float *a, __global float *b, __global float *c) {" + " size_t idx = get_global_id(0)" + " c[idx] = a[idx] + b[idx]; }"; +const char *source1 = + "__kernel void incr(__global float *x) {" + " ++x[get_global_id(0)]; }" + "__kernel void scale(float a, __global float *x) {" + " x[get_global_id(0)] *= a; }"; +const char *source2 = + "void sgemm( float alpha" + " float beta," + " __global float *Ad," + " __global float *Bd," + " __global float *Cd," + " int width) {" + " int col = get_global_id(0);" + " int row = get_global_id(1);" + " float sum = 0;" + " for (int k = 0; k < width; k+=1)" + " sum += Ad[row * width + k] * Bd[k * width + col];" + " Cd[row * width + col] = alpha * sum + beta * Cd[row * width + col];" + "}"; + +cl_platform_id getPlatform() { + cl_platform_id platform = nullptr; + cl_uint num_platforms = 0; + size_t param_value_size = 0; + cl_int err = CL_SUCCESS; + + err = clGetPlatformIDs(1, &platform, &num_platforms); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_MESSAGE(num_platforms >= 1, "No platform found"); + + /* platform should be 'dOpenCL' */ + err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, nullptr, + ¶m_value_size); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + char platform_name[param_value_size]; + err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, param_value_size, + platform_name, nullptr); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_CHECK_MESSAGE(strcmp(platform_name, "dOpenCL") == 0, "First platform must be 'dOpenCL'"); + + return platform; +} + +void getComputeNodes(cl_platform_id platform, cl_uint num_nodes, cl_compute_node_WWU *nodes) { + cl_uint num_nodes_ret = 0; + + cl_int err = clGetComputeNodesWWU(platform, num_nodes, nodes, &num_nodes_ret); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_MESSAGE(num_nodes_ret >= num_nodes, "No enough compute nodes"); +} + +void getDevices(cl_platform_id platform, cl_device_type type, cl_uint num_devices, cl_device_id *devices) { + cl_uint num_devices_ret = 0; + + cl_int err = clGetDeviceIDs(platform, type, num_devices, devices, + &num_devices_ret); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE_MESSAGE(num_devices_ret >= num_devices, "No enough devices"); +} + +cl_device_id getDevice(cl_platform_id platform) { + cl_device_id device = nullptr; + cl_uint num_devices = 0; + + cl_int err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, + &num_devices); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(device != nullptr); + BOOST_REQUIRE_GE(num_devices, 1); + + return device; +} + +cl_device_id getDevice(cl_compute_node_WWU node) { + cl_device_id device = nullptr; + cl_uint num_devices = 0; + + cl_int err = clGetDeviceIDsFromComputeNodeWWU(node, CL_DEVICE_TYPE_ALL, 1, &device, + &num_devices); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(device != nullptr); + BOOST_REQUIRE_GE(num_devices, 1); + + return device; +} + +cl_context createContext(cl_uint num_devices, cl_device_id *devices) { + cl_int err = CL_SUCCESS; + + BOOST_REQUIRE_GE(num_devices, 1); + BOOST_REQUIRE(devices != nullptr); + + cl_context context = clCreateContext(0, num_devices, devices, 0, 0, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(context != nullptr); + + return context; +} + +cl_command_queue createCommandQueue(cl_context context, cl_device_id device, + cl_command_queue_properties properties) { + cl_int err = CL_SUCCESS; + + cl_command_queue commandQueue = clCreateCommandQueue(context, device, properties, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(commandQueue != nullptr); + + return commandQueue; +} + +cl_program createProgramWithSource( + cl_context context, + cl_uint num_sources, + const char **sources, + size_t *lengths) { + cl_int err = CL_SUCCESS; + + cl_program program = clCreateProgramWithSource(context, num_sources, sources, lengths, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(program != nullptr); + + return program; +} + +cl_mem createRWBuffer(cl_context context, size_t cb) { + cl_int err = CL_SUCCESS; + + cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, cb, nullptr, &err); + BOOST_REQUIRE_EQUAL(err, CL_SUCCESS); + BOOST_REQUIRE(buffer != nullptr); + + return buffer; +} + +} // namespace dcltest diff --git a/test/src/utility.h b/test/src/utility.h new file mode 100644 index 0000000..eeae743 --- /dev/null +++ b/test/src/utility.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * This file is part of dOpenCL. + * + * dOpenCL is an implementation of the OpenCL application programming + * interface for distributed systems. See + * for more information. + * + * Developed by: Research Group Parallel and Distributed Systems + * Department of Mathematics and Computer Science + * University of Muenster, Germany + * + * + * Copyright (C) 2013 Philipp Kegel + * + * dOpenCL is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dOpenCL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dOpenCL. If not, see . + * + * Permission to use dOpenCL for scientific, non-commercial work is + * granted under the terms of the dOpenCL Academic License provided + * appropriate credit is given. See the dOpenCL Academic License for + * more details. + * + * You should have received a copy of the dOpenCL Academic License + * along with dOpenCL. If not, see . + ******************************************************************************/ + +/*! + * \file utility.h + * + * \date 2013-12-08 + * \author Philipp Kegel + */ + +#ifndef UTILITY_H_ +#define UTILITY_H_ + +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + +#include + +namespace dcltest { + +extern const char *source; //!< example source code +extern const char *source1; //!< example source code 1 +extern const char *source2; //!< example source code 2 + +/*! + * \brief Returns the dOpenCL platform + * + * \return the dOpenCL platform + */ +cl_platform_id getPlatform(); + +/*! + * \brief Obtains the specified number of compute nodes from the given platform. + * + * \param[in] platform + * \param[in] num_nodes + * \param[out] nodes + */ +void getComputeNodes( + cl_platform_id platform, + cl_uint num_nodes, + cl_compute_node_WWU *nodes); + +/*! + * \brief Obtains the specified number of compute nodes from the given platform. + * + * \param[in] platform the platform + * \param[in] tyoe type of devices to obtain + * \param[in] num_devices number of devices to obtain + * \param[out] devices the devices + */ +void getDevices( + cl_platform_id platform, + cl_device_type type, + cl_uint num_devices, + cl_device_id *devices); + +/*! + * \brief Returns the specified platform's first device. + * + * \param[in] platform the platform + * \return the platform's first device + */ +cl_device_id getDevice( + cl_platform_id platform); + +/*! + * \brief Returns the specified compute node's first device. + * + * \param[in] node the compute node + * \return the compute node's first device + */ +cl_device_id getDevice( + cl_compute_node_WWU node); + +cl_context createContext( + cl_uint num_devices, + cl_device_id *devices); + +cl_command_queue createCommandQueue( + cl_context context, + cl_device_id device, + cl_command_queue_properties properties = 0); + +cl_program createProgramWithSource( + cl_context context, + cl_uint num_sources, + const char **sources, + size_t *lengths = nullptr); + +cl_mem createRWBuffer( + cl_context context, + size_t cb); + +/* ****************************************************************************/ + +/*! + * \brief Fills a vector with values + * + * \param[out] vec vector to fill + * \param[in] first first value + * \param[in] step steps between consecutive values + */ +template +void fillVector(std::vector& vec, T first, T step) { + T value = first; + for (auto& item : vec) { + item = value; + value += step; + } +} + +} // namespace dcltest + +#endif /* UTILITY_H_ */