125 lines
4.1 KiB
C++
125 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include <c10/core/impl/InlineEvent.h>
|
|
#include <c10/core/impl/VirtualGuardImpl.h>
|
|
|
|
namespace c10 {
|
|
|
|
/**
|
|
* A backend-generic movable, not copyable, not thread-safe event.
|
|
*
|
|
* The design of this event follows that of CUDA and HIP events. These events
|
|
* are recorded and waited on by streams and can be rerecorded to,
|
|
* each rerecording essentially creating a new version of the event.
|
|
* For example, if (in CPU time), stream X is asked to record E,
|
|
* stream Y waits on E, and stream X is asked to record E again, then Y will
|
|
* wait for X to finish the first call to record and not the second, because
|
|
* it's waiting on the first version of event E, not the second.
|
|
* Querying an event only returns the status of its most recent version.
|
|
*
|
|
* Backend-generic events are implemented by this class and
|
|
* impl::InlineEvent. In addition to these events there are also
|
|
* some backend-specific events, like ATen's CUDAEvent. Each of these
|
|
* classes has its own use.
|
|
*
|
|
* impl::InlineEvent<...> or a backend-specific event should be
|
|
* preferred when the backend is known at compile time and known to
|
|
* be compiled. Backend-specific events may have additional functionality.
|
|
*
|
|
* This Event should be used if a particular backend may not be available,
|
|
* or the backend required is not known at compile time.
|
|
*
|
|
* These generic events are built on top of DeviceGuardImpls, analogous
|
|
* to DeviceGuard and InlineDeviceGuard. The name "DeviceGuardImpls,"
|
|
* is no longer entirely accurate, as these classes implement the
|
|
* backend-specific logic for a generic backend interface.
|
|
*
|
|
* See DeviceGuardImplInterface.h for a list of all supported flags.
|
|
*/
|
|
|
|
struct Event final {
|
|
// Constructors
|
|
Event() = delete;
|
|
Event(
|
|
const DeviceType _device_type,
|
|
const EventFlag _flag = EventFlag::PYTORCH_DEFAULT)
|
|
: impl_{_device_type, _flag} {}
|
|
|
|
// Copy constructor and copy assignment operator (deleted)
|
|
Event(const Event&) = delete;
|
|
Event& operator=(const Event&) = delete;
|
|
|
|
// Move constructor and move assignment operator
|
|
Event(Event&& other) noexcept : impl_{std::move(other.impl_)} {}
|
|
Event& operator=(Event&& other) noexcept {
|
|
impl_.swap(std::move(other.impl_));
|
|
return *this;
|
|
}
|
|
|
|
// Destructor
|
|
~Event() = default;
|
|
|
|
// Getters
|
|
Device device() const noexcept {
|
|
return Device(device_type(), device_index());
|
|
}
|
|
DeviceType device_type() const noexcept {
|
|
return impl_.device_type();
|
|
}
|
|
DeviceIndex device_index() const noexcept {
|
|
return impl_.device_index();
|
|
}
|
|
EventFlag flag() const noexcept {
|
|
return impl_.flag();
|
|
}
|
|
bool was_marked_for_recording() const noexcept {
|
|
return impl_.was_marked_for_recording();
|
|
}
|
|
|
|
/**
|
|
* Calls record() if and only if record() has never been called for this
|
|
* event. Note: because Event is not thread-safe recordOnce() may call
|
|
* record() multiple times if called from multiple threads.
|
|
*/
|
|
void recordOnce(const Stream& stream) {
|
|
impl_.recordOnce(stream);
|
|
}
|
|
|
|
/**
|
|
* Increments the event's version and enqueues a job with this version
|
|
* in the stream's work queue. When the stream process that job
|
|
* it notifies all streams waiting on / blocked by that version of the
|
|
* event to continue and marks that version as recorded.
|
|
* */
|
|
void record(const Stream& stream) {
|
|
impl_.record(stream);
|
|
}
|
|
|
|
/**
|
|
* Does nothing if the event has not been scheduled to be recorded.
|
|
* If the event was previously enqueued to be recorded, a command
|
|
* to wait for the version of the event that exists at the time of this call
|
|
* is inserted in the stream's work queue.
|
|
* When the stream reaches this command it will stop processing
|
|
* additional commands until that version of the event is marked as recorded.
|
|
*/
|
|
void block(const Stream& stream) const {
|
|
impl_.block(stream);
|
|
}
|
|
|
|
/**
|
|
* Returns true if (and only if)
|
|
* (1) the event has never been scheduled to be recorded
|
|
* (2) the current version is marked as recorded.
|
|
* Returns false otherwise.
|
|
*/
|
|
bool query() const {
|
|
return impl_.query();
|
|
}
|
|
|
|
private:
|
|
impl::InlineEvent<impl::VirtualGuardImpl> impl_;
|
|
};
|
|
|
|
} // namespace c10
|