File: Event.h

package info (click to toggle)
pytorch-cuda 2.6.0%2Bdfsg-7
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 161,620 kB
  • sloc: python: 1,278,832; cpp: 900,322; ansic: 82,710; asm: 7,754; java: 3,363; sh: 2,811; javascript: 2,443; makefile: 597; ruby: 195; xml: 84; objc: 68
file content (137 lines) | stat: -rw-r--r-- 4,463 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#pragma once

#include <c10/core/Device.h>
#include <c10/core/DeviceType.h>
#include <c10/core/Stream.h>
#include <c10/core/impl/DeviceGuardImplInterface.h>
#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&&) noexcept = default;
  Event& operator=(Event&&) noexcept = default;

  // 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();
  }

  double elapsedTime(const Event& event) const {
    return impl_.elapsedTime(event.impl_);
  }

  void* eventId() const {
    return impl_.eventId();
  }

  void synchronize() const {
    return impl_.synchronize();
  }

 private:
  impl::InlineEvent<impl::VirtualGuardImpl> impl_;
};

} // namespace c10