From f81054dfacc83b4897e459c55edb2badd85b4caf Mon Sep 17 00:00:00 2001 From: dmed256 Date: Thu, 6 Sep 2018 02:40:00 -0500 Subject: [PATCH] [StreamTag] Split streamTag as a modeStreamTag_t --- include/occa/base.hpp | 1 + include/occa/c/types.h | 7 +- include/occa/c/types.hpp | 11 +- include/occa/device.hpp | 31 ++--- include/occa/mode/cuda/device.hpp | 6 +- include/occa/mode/cuda/streamTag.hpp | 48 ++++++++ include/occa/mode/cuda/utils.hpp | 3 - include/occa/mode/opencl/device.hpp | 6 +- include/occa/mode/opencl/streamTag.hpp | 50 ++++++++ include/occa/mode/opencl/utils.hpp | 3 - include/occa/mode/serial/device.hpp | 6 +- include/occa/mode/serial/streamTag.hpp | 44 +++++++ include/occa/stream.hpp | 1 - include/occa/streamTag.hpp | 95 ++++++++++++++++ src/c/base.cpp | 5 +- src/c/device.cpp | 5 +- src/c/types.cpp | 41 +++++-- src/device.cpp | 22 ++-- src/kernel.cpp | 2 +- src/memory.cpp | 2 +- src/mode/cuda/device.cpp | 37 ++++-- src/mode/cuda/streamTag.cpp | 44 +++++++ src/mode/cuda/utils.cpp | 8 -- src/mode/opencl/device.cpp | 48 ++++---- src/mode/opencl/stream.cpp | 2 +- src/mode/opencl/streamTag.cpp | 58 ++++++++++ src/mode/opencl/utils.cpp | 9 +- src/mode/serial/device.cpp | 22 ++-- src/mode/serial/serialTag.cpp | 36 ++++++ src/stream.cpp | 16 +-- src/streamTag.cpp | 151 +++++++++++++++++++++++++ 31 files changed, 665 insertions(+), 155 deletions(-) create mode 100644 include/occa/mode/cuda/streamTag.hpp create mode 100644 include/occa/mode/opencl/streamTag.hpp create mode 100644 include/occa/mode/serial/streamTag.hpp create mode 100644 include/occa/streamTag.hpp create mode 100644 src/mode/cuda/streamTag.cpp create mode 100644 src/mode/opencl/streamTag.cpp create mode 100644 src/mode/serial/serialTag.cpp create mode 100644 src/streamTag.cpp diff --git a/include/occa/base.hpp b/include/occa/base.hpp index 01fa6e2c8..941072248 100644 --- a/include/occa/base.hpp +++ b/include/occa/base.hpp @@ -39,6 +39,7 @@ #include #include #include +#include namespace occa { //---[ Device Functions ]------------- diff --git a/include/occa/c/types.h b/include/occa/c/types.h index aa98bc88d..5f06df4f4 100644 --- a/include/occa/c/types.h +++ b/include/occa/c/types.h @@ -65,15 +65,11 @@ typedef occaType occaDevice; typedef occaType occaKernel; typedef occaType occaMemory; typedef occaType occaStream; +typedef occaType occaStreamTag; typedef occaType occaJson; typedef occaType occaProperties; -typedef struct { - double tagTime; - void *modeTag; -} occaStreamTag; - //---[ Type Flags ]--------------------- extern const int OCCA_UNDEFINED; extern const int OCCA_DEFAULT; @@ -99,6 +95,7 @@ extern const int OCCA_DEVICE; extern const int OCCA_KERNEL; extern const int OCCA_MEMORY; extern const int OCCA_STREAM; +extern const int OCCA_STREAMTAG; extern const int OCCA_JSON; extern const int OCCA_PROPERTIES; diff --git a/include/occa/c/types.hpp b/include/occa/c/types.hpp index 52552f8c3..5897e117d 100644 --- a/include/occa/c/types.hpp +++ b/include/occa/c/types.hpp @@ -53,9 +53,10 @@ namespace occa { static const int kernel = 17; static const int memory = 18; static const int stream = 19; + static const int streamTag = 20; - static const int json = 20; - static const int properties = 21; + static const int json = 21; + static const int properties = 22; } occaType defaultOccaType(); @@ -110,6 +111,7 @@ namespace occa { occaType newOccaType(occa::kernel kernel); occaType newOccaType(occa::memory memory); occaType newOccaType(occa::stream stream); + occaType newOccaType(occa::streamTag streamTag); occaType newOccaType(const json &json, const bool needsFree); @@ -117,14 +119,13 @@ namespace occa { occaType newOccaType(const occa::properties &properties, const bool needsFree); - occaStreamTag newOccaType(occa::streamTag value); - bool isDefault(occaType value); occa::device device(occaType value); occa::kernel kernel(occaType value); occa::memory memory(occaType value); occa::stream stream(occaType value); + occa::streamTag streamTag(occaType value); occa::primitive primitive(occaType value); occa::primitive primitive(occaType value, @@ -135,7 +136,5 @@ namespace occa { occa::properties& properties(occaType value); const occa::properties& constProperties(occaType value); - - occa::streamTag streamTag(occaStreamTag value); } } diff --git a/include/occa/device.hpp b/include/occa/device.hpp index d58947adf..9deafc3aa 100644 --- a/include/occa/device.hpp +++ b/include/occa/device.hpp @@ -36,10 +36,9 @@ namespace occa { class modeKernel_t; class kernel; class modeMemory_t; class memory; class modeDevice_t; class device; + class modeStreamTag_t; class streamTag; class deviceInfo; - class streamTag; - typedef std::map cachedKernelMap; typedef cachedKernelMap::iterator cachedKernelMapIterator; typedef cachedKernelMap::const_iterator cCachedKernelMapIterator; @@ -54,6 +53,7 @@ namespace occa { gc::ring_t kernelRing; gc::ring_t memoryRing; gc::ring_t streamRing; + gc::ring_t streamTagRing; ptrRangeMap uvaMap; memoryVector uvaStaleMemory; @@ -83,6 +83,7 @@ namespace occa { } } + // Must be called before ~modeDevice_t()! void freeResources(); void dontUseRefs(); @@ -99,6 +100,9 @@ namespace occa { void addStreamRef(modeStream_t *stream); void removeStreamRef(modeStream_t *stream); + void addStreamTagRef(modeStreamTag_t *streamTag); + void removeStreamTagRef(modeStreamTag_t *streamTag); + //---[ Virtual Methods ]------------ virtual ~modeDevice_t() = 0; @@ -113,10 +117,10 @@ namespace occa { // |---[ Stream ]------------------ virtual modeStream_t* createStream(const occa::properties &props) = 0; - virtual streamTag tagStream() const = 0; - virtual void waitFor(streamTag tag) const = 0; + virtual streamTag tagStream() = 0; + virtual void waitFor(streamTag tag) = 0; virtual double timeBetween(const streamTag &startTag, - const streamTag &endTag) const = 0; + const streamTag &endTag) = 0; // |=============================== // |---[ Kernel ]------------------ @@ -283,21 +287,6 @@ namespace occa { std::ostream& operator << (std::ostream &out, const occa::device &device); //==================================== - - //---[ stream ]----------------------- - /* - * CUDA : modeTag = CUevent* - * OpenCL : modeTag = cl_event* - */ - class streamTag { - public: - double tagTime; - void *modeTag; - - streamTag(); - streamTag(const double tagTime_, - void *modeTag_); - }; - //==================================== } + #endif diff --git a/include/occa/mode/cuda/device.hpp b/include/occa/mode/cuda/device.hpp index 459473f67..3157829b3 100644 --- a/include/occa/mode/cuda/device.hpp +++ b/include/occa/mode/cuda/device.hpp @@ -60,10 +60,10 @@ namespace occa { //---[ Stream ]------------------- virtual modeStream_t* createStream(const occa::properties &props); - virtual streamTag tagStream() const; - virtual void waitFor(streamTag tag) const; + virtual streamTag tagStream(); + virtual void waitFor(streamTag tag); virtual double timeBetween(const streamTag &startTag, - const streamTag &endTag) const; + const streamTag &endTag); CUstream& getCuStream() const; //================================ diff --git a/include/occa/mode/cuda/streamTag.hpp b/include/occa/mode/cuda/streamTag.hpp new file mode 100644 index 000000000..24d7e5e6a --- /dev/null +++ b/include/occa/mode/cuda/streamTag.hpp @@ -0,0 +1,48 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include + +#if OCCA_CUDA_ENABLED +# ifndef OCCA_MODES_CUDA_STREAMTAG_HEADER +# define OCCA_MODES_CUDA_STREAMTAG_HEADER + +#include + +#include + +namespace occa { + namespace cuda { + class streamTag : public occa::modeStreamTag_t { + public: + CUevent cuEvent; + + streamTag(modeDevice_t *modeDevice_, + CUevent cuEvent_); + + virtual ~streamTag(); + }; + } +} + +# endif +#endif diff --git a/include/occa/mode/cuda/utils.hpp b/include/occa/mode/cuda/utils.hpp index cfd6d79be..588fde553 100644 --- a/include/occa/mode/cuda/utils.hpp +++ b/include/occa/mode/cuda/utils.hpp @@ -109,9 +109,6 @@ namespace occa { const udim_t bytes, const occa::properties &props = occa::properties()); - CUevent& event(streamTag &tag); - const CUevent& event(const streamTag &tag); - void warn(CUresult errorCode, const std::string &filename, const std::string &function, diff --git a/include/occa/mode/opencl/device.hpp b/include/occa/mode/opencl/device.hpp index 7b6d9d07a..58c8e81d3 100644 --- a/include/occa/mode/opencl/device.hpp +++ b/include/occa/mode/opencl/device.hpp @@ -59,10 +59,10 @@ namespace occa { //---[ Stream ]------------------- virtual modeStream_t* createStream(const occa::properties &props); - virtual streamTag tagStream() const; - virtual void waitFor(streamTag tag) const; + virtual streamTag tagStream(); + virtual void waitFor(streamTag tag); virtual double timeBetween(const streamTag &startTag, - const streamTag &endTag) const; + const streamTag &endTag); cl_command_queue& getCommandQueue() const; //================================ diff --git a/include/occa/mode/opencl/streamTag.hpp b/include/occa/mode/opencl/streamTag.hpp new file mode 100644 index 000000000..f6b92e6f9 --- /dev/null +++ b/include/occa/mode/opencl/streamTag.hpp @@ -0,0 +1,50 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include + +#if OCCA_OPENCL_ENABLED +# ifndef OCCA_MODES_OPENCL_STREAMTAG_HEADER +# define OCCA_MODES_OPENCL_STREAMTAG_HEADER + +#include +#include + +namespace occa { + namespace opencl { + class streamTag : public occa::modeStreamTag_t { + public: + cl_event clEvent; + double time; + + streamTag(modeDevice_t *modeDevice_, + cl_event clEvent_); + + virtual ~streamTag(); + + double getTime(); + }; + } +} + +# endif +#endif diff --git a/include/occa/mode/opencl/utils.hpp b/include/occa/mode/opencl/utils.hpp index 4f9f940ab..84e97dc5f 100644 --- a/include/occa/mode/opencl/utils.hpp +++ b/include/occa/mode/opencl/utils.hpp @@ -132,9 +132,6 @@ namespace occa { const udim_t bytes, const occa::properties &props = occa::properties()); - cl_event& event(streamTag &tag); - const cl_event& event(const streamTag &tag); - void warn(cl_int errorCode, const std::string &filename, const std::string &function, diff --git a/include/occa/mode/serial/device.hpp b/include/occa/mode/serial/device.hpp index b35a3c249..35ed113e4 100644 --- a/include/occa/mode/serial/device.hpp +++ b/include/occa/mode/serial/device.hpp @@ -46,10 +46,10 @@ namespace occa { //---[ Stream ]------------------- virtual modeStream_t* createStream(const occa::properties &props); - virtual streamTag tagStream() const; - virtual void waitFor(streamTag tag) const; + virtual streamTag tagStream(); + virtual void waitFor(streamTag tag); virtual double timeBetween(const streamTag &startTag, - const streamTag &endTag) const; + const streamTag &endTag); //================================ //---[ Kernel ]------------------- diff --git a/include/occa/mode/serial/streamTag.hpp b/include/occa/mode/serial/streamTag.hpp new file mode 100644 index 000000000..b7339347c --- /dev/null +++ b/include/occa/mode/serial/streamTag.hpp @@ -0,0 +1,44 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include + +#ifndef OCCA_MODES_SERIAL_STREAMTAG_HEADER +#define OCCA_MODES_SERIAL_STREAMTAG_HEADER + +#include + +namespace occa { + namespace serial { + class streamTag : public occa::modeStreamTag_t { + public: + double time; + + streamTag(modeDevice_t *modeDevice_, + double time_); + + virtual ~streamTag(); + }; + } +} + +#endif diff --git a/include/occa/stream.hpp b/include/occa/stream.hpp index 699fac379..232689ccf 100644 --- a/include/occa/stream.hpp +++ b/include/occa/stream.hpp @@ -73,7 +73,6 @@ namespace occa { ~stream(); private: - void assertInitialized() const; void setModeStream(modeStream_t *modeStream_); void removeStreamRef(); diff --git a/include/occa/streamTag.hpp b/include/occa/streamTag.hpp new file mode 100644 index 000000000..639a66c45 --- /dev/null +++ b/include/occa/streamTag.hpp @@ -0,0 +1,95 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#ifndef OCCA_STREAMTAG_HEADER +#define OCCA_STREAMTAG_HEADER + +#include + +#include +#include + +namespace occa { + class modeDevice_t; class device; + class modeStreamTag_t; class streamTag; + + //---[ modeStreamTag_t ]--------------------- + class modeStreamTag_t : public gc::ringEntry_t { + public: + gc::ring_t streamTagRing; + + modeDevice_t *modeDevice; + + modeStreamTag_t(modeDevice_t *modeDevice_); + + void dontUseRefs(); + void addStreamTagRef(streamTag *s); + void removeStreamTagRef(streamTag *s); + bool needsFree() const; + + //---[ Virtual Methods ]------------ + virtual ~modeStreamTag_t(); + //================================== + }; + //==================================== + + //---[ streamTag ]----------------------- + class streamTag : public gc::ringEntry_t { + friend class occa::modeStreamTag_t; + friend class occa::device; + + private: + modeStreamTag_t *modeStreamTag; + + public: + streamTag(); + streamTag(modeStreamTag_t *modeStreamTag_); + + streamTag(const streamTag &s); + streamTag& operator = (const streamTag &m); + ~streamTag(); + + private: + void setModeStreamTag(modeStreamTag_t *modeStreamTag_); + void removeStreamTagRef(); + + public: + void dontUseRefs(); + + bool isInitialized() const; + + modeStreamTag_t* getModeStreamTag() const; + modeDevice_t* getModeDevice() const; + + occa::device getDevice() const; + + void wait() const; + + bool operator == (const occa::streamTag &other) const; + bool operator != (const occa::streamTag &other) const; + + void free(); + }; + //==================================== +} + +#endif diff --git a/src/c/base.cpp b/src/c/base.cpp index 29d793469..d6f3b3d12 100644 --- a/src/c/base.cpp +++ b/src/c/base.cpp @@ -88,7 +88,10 @@ void OCCA_RFUNC occaSetStream(occaStream stream) { } occaStreamTag OCCA_RFUNC occaTagStream() { - return occa::c::newOccaType(occa::tagStream()); + occa::streamTag tag = occa::tagStream(); + tag.dontUseRefs(); + + return occa::c::newOccaType(tag); } void OCCA_RFUNC occaWaitForTag(occaStreamTag tag) { diff --git a/src/c/device.cpp b/src/c/device.cpp index 2bb35b05d..ee6e34294 100644 --- a/src/c/device.cpp +++ b/src/c/device.cpp @@ -117,7 +117,10 @@ void OCCA_RFUNC occaDeviceSetStream(occaDevice device, occaStreamTag OCCA_RFUNC occaDeviceTagStream(occaDevice device) { occa::device device_ = occa::c::device(device); - return occa::c::newOccaType(device_.tagStream()); + occa::streamTag tag = device_.tagStream(); + tag.dontUseRefs(); + + return occa::c::newOccaType(tag); } void OCCA_RFUNC occaDeviceWaitForTag(occaDevice device, diff --git a/src/c/types.cpp b/src/c/types.cpp index acc6bab21..b82c98558 100644 --- a/src/c/types.cpp +++ b/src/c/types.cpp @@ -268,6 +268,21 @@ namespace occa { return oType; } + occaType newOccaType(occa::streamTag streamTag) { + occa::modeStreamTag_t *modeStreamTag = streamTag.getModeStreamTag(); + if (!modeStreamTag) { + return occaUndefined; + } + + occaType oType; + oType.magicHeader = OCCA_C_TYPE_MAGIC_HEADER; + oType.type = typeType::streamTag; + oType.bytes = sizeof(void*); + oType.value.ptr = (char*) modeStreamTag; + oType.needsFree = false; + return oType; + } + occaType newOccaType(const occa::json &json, const bool needsFree) { if (json.isNull()) { @@ -293,13 +308,6 @@ namespace occa { return oType; } - occaStreamTag newOccaType(occa::streamTag value) { - occaStreamTag tag; - tag.tagTime = value.tagTime; - tag.modeTag = value.modeTag; - return tag; - } - bool isDefault(occaType value) { return (value.type == typeType::default_); } @@ -340,6 +348,15 @@ namespace occa { return occa::stream((occa::modeStream_t*) value.value.ptr); } + occa::streamTag streamTag(occaType value) { + if (occaIsUndefined(value)) { + return occa::streamTag(); + } + OCCA_ERROR("Input is not an occaStreamTag", + value.type == typeType::streamTag); + return occa::streamTag((occa::modeStreamTag_t*) value.value.ptr); + } + occa::primitive primitive(occaType value) { occa::primitive p; @@ -440,11 +457,6 @@ namespace occa { value.type == typeType::properties); return *((const occa::properties*) value.value.ptr); } - - occa::streamTag streamTag(occaStreamTag value) { - return occa::streamTag(value.tagTime, - value.modeTag); - } } } @@ -476,6 +488,7 @@ const int OCCA_DEVICE = occa::c::typeType::device; const int OCCA_KERNEL = occa::c::typeType::kernel; const int OCCA_MEMORY = occa::c::typeType::memory; const int OCCA_STREAM = occa::c::typeType::stream; +const int OCCA_STREAMTAG = occa::c::typeType::streamTag; const int OCCA_JSON = occa::c::typeType::json; const int OCCA_PROPERTIES = occa::c::typeType::properties; @@ -623,6 +636,10 @@ OCCA_LFUNC void OCCA_RFUNC occaFree(occaType value) { occa::c::stream(value).free(); break; } + case occa::c::typeType::streamTag: { + occa::c::streamTag(value).free(); + break; + } case occa::c::typeType::json: { if (value.needsFree) { delete &occa::c::json(value); diff --git a/src/device.cpp b/src/device.cpp index 14a5d7244..cb3b2f6fa 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -28,7 +28,7 @@ #include namespace occa { - //---[ modeDevice_t ]--------------------- + //---[ modeDevice_t ]----------------- modeDevice_t::modeDevice_t(const occa::properties &properties_) : mode((std::string) properties_["mode"]), properties(properties_), @@ -52,6 +52,7 @@ namespace occa { freeRing(kernelRing); freeRing(memoryRing); freeRing(streamRing); + freeRing(streamTagRing); } void modeDevice_t::dontUseRefs() { @@ -94,6 +95,14 @@ namespace occa { streamRing.removeRef(stream); } + void modeDevice_t::addStreamTagRef(modeStreamTag_t *streamTag) { + streamTagRing.addRef(streamTag); + } + + void modeDevice_t::removeStreamTagRef(modeStreamTag_t *streamTag) { + streamTagRing.removeRef(streamTag); + } + hash_t modeDevice_t::versionedHash() const { return (occa::hash(settings()["version"]) ^ hash()); @@ -635,15 +644,4 @@ namespace occa { return out; } //==================================== - - //---[ streamTag ]-------------------- - streamTag::streamTag() : - tagTime(0), - modeTag(NULL) {} - - streamTag::streamTag(const double tagTime_, - void *modeTag_) : - tagTime(tagTime_), - modeTag(modeTag_) {} - //==================================== } diff --git a/src/kernel.cpp b/src/kernel.cpp index 87d1293de..5fa1fd7fa 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -31,7 +31,7 @@ #include namespace occa { - //---[ modeKernel_t ]--------------------- + //---[ modeKernel_t ]----------------- modeKernel_t::modeKernel_t(modeDevice_t *modeDevice_, const std::string &name_, const std::string &sourceFilename_, diff --git a/src/memory.cpp b/src/memory.cpp index 2809db1af..06476cb8b 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -30,7 +30,7 @@ #include namespace occa { - //---[ modeMemory_t ]--------------------- + //---[ modeMemory_t ]----------------- modeMemory_t::modeMemory_t(modeDevice_t *modeDevice_, udim_t size_, const occa::properties &properties_) : diff --git a/src/mode/cuda/device.cpp b/src/mode/cuda/device.cpp index 22b63ff4a..db365e359 100644 --- a/src/mode/cuda/device.cpp +++ b/src/mode/cuda/device.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -132,32 +133,44 @@ namespace occa { return new stream(this, props, cuStream); } - streamTag device::tagStream() const { - streamTag ret; + occa::streamTag device::tagStream() { + CUevent cuEvent; OCCA_CUDA_ERROR("Device: Setting Context", cuCtxSetCurrent(cuContext)); OCCA_CUDA_ERROR("Device: Tagging Stream (Creating Tag)", - cuEventCreate(&cuda::event(ret), CU_EVENT_DEFAULT)); + cuEventCreate(&cuEvent, + CU_EVENT_DEFAULT)); OCCA_CUDA_ERROR("Device: Tagging Stream", - cuEventRecord(cuda::event(ret), 0)); + cuEventRecord(cuEvent, 0)); - return ret; + return new occa::cuda::streamTag(this, cuEvent); } - void device::waitFor(streamTag tag) const { + void device::waitFor(occa::streamTag tag) { + occa::cuda::streamTag *cuTag = ( + dynamic_cast(tag.getModeStreamTag()) + ); OCCA_CUDA_ERROR("Device: Waiting For Tag", - cuEventSynchronize(cuda::event(tag))); + cuEventSynchronize(cuTag->cuEvent)); } - double device::timeBetween(const streamTag &startTag, - const streamTag &endTag) const { - OCCA_CUDA_ERROR("Device: Waiting for endTag", - cuEventSynchronize(cuda::event(endTag))); + double device::timeBetween(const occa::streamTag &startTag, + const occa::streamTag &endTag) { + occa::cuda::streamTag *cuStartTag = ( + dynamic_cast(startTag.getModeStreamTag()) + ); + occa::cuda::streamTag *cuEndTag = ( + dynamic_cast(endTag.getModeStreamTag()) + ); + + waitFor(endTag); float msTimeTaken; OCCA_CUDA_ERROR("Device: Timing Between Tags", - cuEventElapsedTime(&msTimeTaken, cuda::event(startTag), cuda::event(endTag))); + cuEventElapsedTime(&msTimeTaken, + cuStartTag->cuEvent, + cuEndTag->cuEvent)); return (double) (1.0e-3 * (double) msTimeTaken); } diff --git a/src/mode/cuda/streamTag.cpp b/src/mode/cuda/streamTag.cpp new file mode 100644 index 000000000..5f4834502 --- /dev/null +++ b/src/mode/cuda/streamTag.cpp @@ -0,0 +1,44 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include + +#if OCCA_CUDA_ENABLED + +#include +#include + +namespace occa { + namespace cuda { + streamTag::streamTag(modeDevice_t *modeDevice_, + CUevent cuEvent_) : + modeStreamTag_t(modeDevice_), + cuEvent(cuEvent_) {} + + streamTag::~streamTag() { + OCCA_CUDA_ERROR("streamTag: Freeing CUevent", + cuEventDestroy(cuEvent)); + } + } +} + +#endif diff --git a/src/mode/cuda/utils.cpp b/src/mode/cuda/utils.cpp index 7846821e4..047f5b425 100644 --- a/src/mode/cuda/utils.cpp +++ b/src/mode/cuda/utils.cpp @@ -261,14 +261,6 @@ namespace occa { return occa::memory(&mem); } - CUevent& event(streamTag &tag) { - return (CUevent&) tag.modeTag; - } - - const CUevent& event(const streamTag &tag) { - return (const CUevent&) tag.modeTag; - } - void warn(CUresult errorCode, const std::string &filename, const std::string &function, diff --git a/src/mode/opencl/device.cpp b/src/mode/opencl/device.cpp index dc9420414..2309f537a 100644 --- a/src/mode/opencl/device.cpp +++ b/src/mode/opencl/device.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -120,51 +121,42 @@ namespace occa { return new stream(this, props, commandQueue); } - streamTag device::tagStream() const { - streamTag ret; + occa::streamTag device::tagStream() { + cl_event clEvent; #ifdef CL_VERSION_1_2 OCCA_OPENCL_ERROR("Device: Tagging Stream", clEnqueueMarkerWithWaitList(getCommandQueue(), - 0, NULL, &event(ret))); + 0, NULL, &clEvent)); #else OCCA_OPENCL_ERROR("Device: Tagging Stream", clEnqueueMarker(getCommandQueue(), - &event(ret))); + &clEvent)); #endif - return ret; + return new occa::opencl::streamTag(this, clEvent); } - void device::waitFor(streamTag tag) const { + void device::waitFor(occa::streamTag tag) { + occa::opencl::streamTag *clTag = ( + dynamic_cast(tag.getModeStreamTag()) + ); OCCA_OPENCL_ERROR("Device: Waiting For Tag", - clWaitForEvents(1, &event(tag))); + clWaitForEvents(1, &(clTag->clEvent))); } - double device::timeBetween(const streamTag &startTag, const streamTag &endTag) const { - cl_ulong start, end; + double device::timeBetween(const occa::streamTag &startTag, + const occa::streamTag &endTag) { + occa::opencl::streamTag *clStartTag = ( + dynamic_cast(startTag.getModeStreamTag()) + ); + occa::opencl::streamTag *clEndTag = ( + dynamic_cast(endTag.getModeStreamTag()) + ); finish(); - OCCA_OPENCL_ERROR ("Device: Time Between Tags (Start)", - clGetEventProfilingInfo(event(startTag), - CL_PROFILING_COMMAND_END, - sizeof(cl_ulong), - &start, NULL) ); - - OCCA_OPENCL_ERROR ("Device: Time Between Tags (End)", - clGetEventProfilingInfo(event(endTag), - CL_PROFILING_COMMAND_START, - sizeof(cl_ulong), - &end, NULL) ); - - OCCA_OPENCL_ERROR("Device: Time Between Tags (Freeing start tag)", - clReleaseEvent(event(startTag))); - - OCCA_OPENCL_ERROR("Device: Time Between Tags (Freeing end tag)", - clReleaseEvent(event(endTag))); - - return (double) (1.0e-9 * (double)(end - start)); + return (clStartTag->getTime() - clEndTag->getTime()); } cl_command_queue& device::getCommandQueue() const { diff --git a/src/mode/opencl/stream.cpp b/src/mode/opencl/stream.cpp index c2b506194..38a09764f 100644 --- a/src/mode/opencl/stream.cpp +++ b/src/mode/opencl/stream.cpp @@ -36,7 +36,7 @@ namespace occa { commandQueue(commandQueue_) {} stream::~stream() { - OCCA_OPENCL_ERROR("Device: freeStream", + OCCA_OPENCL_ERROR("Device: Freeing cl_command_queue", clReleaseCommandQueue(commandQueue)); } } diff --git a/src/mode/opencl/streamTag.cpp b/src/mode/opencl/streamTag.cpp new file mode 100644 index 000000000..e3c285e74 --- /dev/null +++ b/src/mode/opencl/streamTag.cpp @@ -0,0 +1,58 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include + +#if OCCA_OPENCL_ENABLED + +#include +#include + +namespace occa { + namespace opencl { + streamTag::streamTag(modeDevice_t *modeDevice_, + cl_event clEvent_) : + modeStreamTag_t(modeDevice_), + clEvent(clEvent_), + time(-1) {} + + streamTag::~streamTag() { + OCCA_OPENCL_ERROR("streamTag: Freeing cl_event", + clReleaseEvent(clEvent)); + } + + double streamTag::getTime() { + if (time < 0) { + cl_ulong clTime; + OCCA_OPENCL_ERROR("streamTag: Getting event profiling info", + clGetEventProfilingInfo(clEvent, + CL_PROFILING_COMMAND_END, + sizeof(cl_ulong), + &clTime, NULL)); + time = 1.0e-9 * clTime; + } + return time; + } + } +} + +#endif diff --git a/src/mode/opencl/utils.cpp b/src/mode/opencl/utils.cpp index 92e03a83f..5454f40c0 100644 --- a/src/mode/opencl/utils.cpp +++ b/src/mode/opencl/utils.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -487,14 +488,6 @@ namespace occa { return occa::memory(&mem); } - cl_event& event(streamTag &tag) { - return (cl_event&) (tag.modeTag); - } - - const cl_event& event(const streamTag &tag) { - return (const cl_event&) (tag.modeTag); - } - void warn(cl_int errorCode, const std::string &filename, const std::string &function, diff --git a/src/mode/serial/device.cpp b/src/mode/serial/device.cpp index 16be3fe59..4bd5f730e 100644 --- a/src/mode/serial/device.cpp +++ b/src/mode/serial/device.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace occa { @@ -138,17 +139,22 @@ namespace occa { return new stream(this, props); } - streamTag device::tagStream() const { - streamTag ret; - ret.tagTime = sys::currentTime(); - return ret; + occa::streamTag device::tagStream() { + return new occa::serial::streamTag(this, sys::currentTime()); } - void device::waitFor(streamTag tag) const {} + void device::waitFor(occa::streamTag tag) {} - double device::timeBetween(const streamTag &startTag, - const streamTag &endTag) const { - return (endTag.tagTime - startTag.tagTime); + double device::timeBetween(const occa::streamTag &startTag, + const occa::streamTag &endTag) { + occa::serial::streamTag *srStartTag = ( + dynamic_cast(startTag.getModeStreamTag()) + ); + occa::serial::streamTag *srEndTag = ( + dynamic_cast(endTag.getModeStreamTag()) + ); + + return (srEndTag->time - srStartTag->time); } //================================== diff --git a/src/mode/serial/serialTag.cpp b/src/mode/serial/serialTag.cpp new file mode 100644 index 000000000..6d0201c62 --- /dev/null +++ b/src/mode/serial/serialTag.cpp @@ -0,0 +1,36 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include + +#include + +namespace occa { + namespace serial { + streamTag::streamTag(modeDevice_t *modeDevice_, + double time_) : + modeStreamTag_t(modeDevice_), + time(time_) {} + + streamTag::~streamTag() {} + } +} diff --git a/src/stream.cpp b/src/stream.cpp index 5f8783138..d8d2b30c3 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -20,13 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -#include - #include #include namespace occa { - //---[ modeStream_t ]--------------------- + //---[ modeStream_t ]----------------- modeStream_t::modeStream_t(modeDevice_t *modeDevice_, const occa::properties &properties_) : properties(properties_), @@ -69,8 +67,7 @@ namespace occa { //---[ stream ]----------------------- stream::stream() : - modeStream(NULL) { - } + modeStream(NULL) {} stream::stream(modeStream_t *modeStream_) : modeStream(NULL) { @@ -91,11 +88,6 @@ namespace occa { removeStreamRef(); } - void stream::assertInitialized() const { - OCCA_ERROR("Stream not initialized or has been freed", - modeStream != NULL); - } - void stream::setModeStream(modeStream_t *modeStream_) { if (modeStream != modeStream_) { removeStreamRef(); @@ -163,10 +155,6 @@ namespace occa { } void stream::free() { - if (!modeStream) { - return; - } - // ~modeStream_t NULLs all wrappers delete modeStream; } diff --git a/src/streamTag.cpp b/src/streamTag.cpp new file mode 100644 index 000000000..fbf9c8688 --- /dev/null +++ b/src/streamTag.cpp @@ -0,0 +1,151 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2014-2018 David Medina and Tim Warburton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the 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 + * AUTHORS 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 IN THE + */ + +#include +#include + +namespace occa { + //---[ modeStreamTag_t ]-------------- + modeStreamTag_t::modeStreamTag_t(modeDevice_t *modeDevice_) : + modeDevice(modeDevice_) { + modeDevice->addStreamTagRef(this); + } + + modeStreamTag_t::~modeStreamTag_t() { + // NULL all wrappers + streamTag *ptr = (streamTag*) streamTagRing.head; + while (ptr) { + streamTag *nextPtr = (streamTag*) ptr->rightRingEntry; + ptr->modeStreamTag = NULL; + ptr->removeRef(); + ptr = ((nextPtr != ptr) + ? nextPtr + : NULL); + } + // Remove ref from device + if (modeDevice) { + modeDevice->removeStreamTagRef(this); + } + } + + void modeStreamTag_t::dontUseRefs() { + streamTagRing.dontUseRefs(); + } + + void modeStreamTag_t::addStreamTagRef(streamTag *s) { + streamTagRing.addRef(s); + } + + void modeStreamTag_t::removeStreamTagRef(streamTag *s) { + streamTagRing.removeRef(s); + } + + bool modeStreamTag_t::needsFree() const { + return streamTagRing.needsFree(); + } + + //---[ streamTag ]----------------------- + streamTag::streamTag() : + modeStreamTag(NULL) {} + + streamTag::streamTag(modeStreamTag_t *modeStreamTag_) : + modeStreamTag(NULL) { + setModeStreamTag(modeStreamTag_); + } + + streamTag::streamTag(const streamTag &m) : + modeStreamTag(NULL) { + setModeStreamTag(m.modeStreamTag); + } + + streamTag& streamTag::operator = (const streamTag &m) { + setModeStreamTag(m.modeStreamTag); + return *this; + } + + streamTag::~streamTag() { + removeStreamTagRef(); + } + + void streamTag::setModeStreamTag(modeStreamTag_t *modeStreamTag_) { + if (modeStreamTag != modeStreamTag_) { + removeStreamTagRef(); + modeStreamTag = modeStreamTag_; + if (modeStreamTag) { + modeStreamTag->addStreamTagRef(this); + } + } + } + + void streamTag::removeStreamTagRef() { + if (!modeStreamTag) { + return; + } + modeStreamTag->removeStreamTagRef(this); + if (modeStreamTag->modeStreamTag_t::needsFree()) { + free(); + } + } + + void streamTag::dontUseRefs() { + if (modeStreamTag) { + modeStreamTag->modeStreamTag_t::dontUseRefs(); + } + } + + bool streamTag::isInitialized() const { + return (modeStreamTag != NULL); + } + + modeStreamTag_t* streamTag::getModeStreamTag() const { + return modeStreamTag; + } + + modeDevice_t* streamTag::getModeDevice() const { + return modeStreamTag->modeDevice; + } + + occa::device streamTag::getDevice() const { + return occa::device(modeStreamTag + ? modeStreamTag->modeDevice + : NULL); + } + + void streamTag::wait() const { + if (modeStreamTag) { + modeStreamTag->modeDevice->waitFor(*this); + } + } + + bool streamTag::operator == (const occa::streamTag &other) const { + return (modeStreamTag == other.modeStreamTag); + } + + bool streamTag::operator != (const occa::streamTag &other) const { + return (modeStreamTag != other.modeStreamTag); + } + + void streamTag::free() { + // ~modeStreamTag_t NULLs all wrappers + delete modeStreamTag; + } +}