| 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) : impl_{std::move(other.impl_)} {} | |
| Event& operator=(Event&& other) { | |
| 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 nofifies 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 | |