doc22_057.md 9.2 KB
Newer Older
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
1 2
# torch.futures

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
3
> 原文:[`pytorch.org/docs/stable/futures.html`](https://pytorch.org/docs/stable/futures.html)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
4

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
5
此软件包提供了一个`Future`类型,封装了异步执行和一组实用函数,以简化对`Future`对象的操作。目前,`Future`类型主要由分布式 RPC 框架使用。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
6 7

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
8
class torch.futures.Future(*, devices=None)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
9 10
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
11
封装了对可调用对象的异步执行的`torch._C.Future`的包装器,例如`rpc_async()`。它还公开了一组 API 来添加回调函数和设置结果。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
12 13 14

警告

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
15
GPU 支持是一个测试功能,可能会发生变化。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
16 17

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
18
add_done_callback(callback)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
19 20
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
21
将给定的回调函数附加到此`Future`,当`Future`完成时将运行该回调。可以向同一个`Future`添加多个回调,但不能保证它们将以何种顺序执行。回调必须接受一个参数,即对此`Future`的引用。回调函数可以使用`value()`方法获取值。请注意,如果此`Future`已经完成,给定的回调将内联运行。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
22

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
23
我们建议您使用`then()`方法,因为它提供了在回调完成后同步的方法。如果您的回调不返回任何内容,`add_done_callback`可能更便宜。但是`then()``add_done_callback`在底层使用相同的回调注册 API。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
24

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
25
就 GPU 张量而言,此方法的行为与`then()`相同。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

参数

**callback** (`Future`) – 一个接受一个参数(即对此`Future`的引用)的`Callable`

注意

请注意,如果回调函数抛出异常,无论是通过原始未来完成异常并调用`fut.wait()`,还是通过回调中的其他代码,都必须小心处理错误处理。例如,如果此回调稍后完成其他未来,那些未来不会被标记为已完成并带有错误,用户需要独立处理完成/等待这些未来。

示例::

```py
>>> def callback(fut):
...     print("This will run after the future has finished.")
...     print(fut.wait())
>>> fut = torch.futures.Future()
>>> fut.add_done_callback(callback)
>>> fut.set_result(5)
This will run after the future has finished.
5 
```

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
49
done()
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
50 51 52 53
```

如果此`Future`已完成,则返回`True`。如果`Future`有结果或异常,则已完成。

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
54
如果值包含在 GPU 上的张量,即使异步内核尚未在设备上完成运行,`Future.done()`将返回`True`,因为在这个阶段结果已经可用,只要执行适当的同步(参见`wait()`)。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
55 56 57 58 59 60

返回类型

[bool](https://docs.python.org/3/library/functions.html#bool "(in Python v3.12)")

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
61
set_exception(result)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
62 63
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
64
为此`Future`设置异常,这将标记此`Future`为已完成并触发所有附加的回调。请注意,当在此`Future`上调用 wait()/value()时,此处设置的异常将内联引发。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

参数

**result** ([*BaseException*](https://docs.python.org/3/library/exceptions.html#BaseException "(in Python v3.12)")) – 此`Future`的异常。

示例::

```py
>>> fut = torch.futures.Future()
>>> fut.set_exception(ValueError("foo"))
>>> fut.wait()
Traceback (most recent call last):
...
ValueError: foo 
```

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
82
set_result(result)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
83 84 85 86
```

设置此`Future`的结果,这将标记此`Future`为已完成并触发所有附加的回调。请注意,`Future`不能被标记为已完成两次。

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
87
如果结果包含驻留在 GPU 上的张量,即使用于填充这些张量的异步内核尚未在设备上完成运行,也可以调用此方法,前提是在调用此方法时将这些内核排队的流设置为当前流。简而言之,只要在启动这些内核后立即调用此方法,而不需要任何额外的同步,就是安全的,只要在其中不更改流。此方法将在所有相关的当前流上记录事件,并将使用它们来确保所有此`Future`的消费者的适当调度。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
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

参数

**result**[*object*](https://docs.python.org/3/library/functions.html#object "(in Python v3.12)"))- 此`Future`的结果对象。

示例::

```py
>>> import threading
>>> import time
>>> def slow_set_future(fut, value):
...     time.sleep(0.5)
...     fut.set_result(value)
>>> fut = torch.futures.Future()
>>> t = threading.Thread(
...     target=slow_set_future,
...     args=(fut, torch.ones(2) * 3)
... )
>>> t.start()
>>> print(fut.wait())
tensor([3., 3.])
>>> t.join() 
```

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
113
then(callback)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
114 115
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
116
将给定的回调函数附加到此`Future`,当`Future`完成时将运行该回调函数。可以向同一个`Future`添加多个回调,但不能保证它们将按照特定顺序执行(要强制执行特定顺序,请考虑链接:`fut.then(cb1).then(cb2)`)。回调函数必须接受一个参数,即对此`Future`的引用。回调函数可以使用`value()`方法获取值。请注意,如果此`Future`已经完成,给定的回调将立即内联运行。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
117

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
118
如果`Future`的值包含驻留在 GPU 上的张量,回调可能在填充这些张量的异步内核尚未在设备上完成执行时被调用。但是,回调将使用一些专用流(从全局池中获取)作为当前流进行调用,这些流将与这些内核同步。因此,回调在这些张量上执行的任何操作将在内核完成后在设备上调度。换句话说,只要回调不切换流,就可以安全地操作结果而无需任何额外的同步。这类似于`wait()`的非阻塞行为。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
119

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
120
同样,如果回调返回一个包含驻留在 GPU 上的张量的值,即使生成这些张量的内核仍在设备上运行,只要回调在执行期间没有更改流,它也可以这样做。如果想要更改流,必须小心地将其重新与原始流同步,即在调用回调时当前的流。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
121 122 123 124 125 126 127 128 129 130 131

参数

**callback**`Callable`)- 一个以此`Future`为唯一参数的`Callable`

返回

一个新的`Future`对象,它保存`callback`的返回值,并在给定的`callback`完成时标记为已完成。

返回类型

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
132
*Future*[*S*]
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
133 134 135

注意

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
136
请注意,如果回调函数抛出异常,要么通过原始 future 完成并调用`fut.wait()`,要么通过回调中的其他代码,`then`返回的 future 将适当标记为遇到的错误。但是,如果此回调稍后完成其他 future,这些 future 不会被标记为带有错误的已完成状态,用户需要独立处理这些 future 的完成/等待。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

示例::

```py
>>> def callback(fut):
...     print(f"RPC return value is {fut.wait()}.")
>>> fut = torch.futures.Future()
>>> # The inserted callback will print the return value when
>>> # receiving the response from "worker1"
>>> cb_fut = fut.then(callback)
>>> chain_cb_fut = cb_fut.then(
...     lambda x : print(f"Chained cb done. {x.wait()}")
... )
>>> fut.set_result(5)
RPC return value is 5.
Chained cb done. None 
```

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
156
value()
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
157 158
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
159
获取已完成 future 的值。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
160

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
161
此方法应该在调用`wait()`完成后调用,或者在传递给`then()`的回调函数中调用。在其他情况下,此`Future`可能尚未持有值,调用`value()`可能会失败。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
162

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
163
如果值包含驻留在 GPU 上的张量,则此方法将*不*执行任何额外的同步。这应该事先单独完成,通过调用`wait()`(除了在回调中,已经通过`then()`处理)。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
164 165 166

返回值

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
167
`Future`持有的值。如果创建值的函数(回调或 RPC)抛出错误,则此`value()`方法也将抛出错误。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
168 169 170 171 172 173

返回类型

*T*

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
174
wait()
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
175 176 177 178
```

阻塞,直到此`Future`的值准备就绪。

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
179
如果值包含驻留在 GPU 上的张量,则会执行与在设备上执行的内核进行的额外同步,这些内核可能是异步填充这些张量。这种同步是非阻塞的,这意味着`wait()`将在当前流中插入必要的指令,以确保在这些流上排队的进一步操作将在异步内核之后正确调度,但是一旦完成,`wait()`将返回,即使这些内核仍在运行。在访问和使用值时不需要进一步的同步,只要不改变流。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
180 181 182

返回值

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
183
`Future`持有的值。如果创建值的函数(回调或 RPC)抛出错误,则此`wait`方法也将抛出错误。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
184 185 186 187 188 189

返回类型

*T*

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
190
torch.futures.collect_all(futures)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
191 192
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
193
将提供的`Future`对象收集到一个单独的组合`Future`中,当所有子 Future 完成时,该组合 Future 完成。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
194 195 196

参数

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
197
**futures**[*列表*](https://docs.python.org/3/library/stdtypes.html#list "(在 Python v3.12 中)"))- 一个`Future`对象的列表。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
198 199 200

返回值

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
201
返回一个`Future`对象到传入 Futures 的列表。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
202 203 204

返回类型

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
205
*Future*[[*列表*](https://docs.python.org/3/library/typing.html#typing.List "(在 Python v3.12 中)")[*Future*]]
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222

示例::

```py
>>> fut0 = torch.futures.Future()
>>> fut1 = torch.futures.Future()
>>> fut = torch.futures.collect_all([fut0, fut1])
>>> fut0.set_result(0)
>>> fut1.set_result(1)
>>> fut_list = fut.wait()
>>> print(f"fut0 result = {fut_list[0].wait()}")
fut0 result = 0
>>> print(f"fut1 result = {fut_list[1].wait()}")
fut1 result = 1 
```

```py
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
223
torch.futures.wait_all(futures)
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
224 225
```

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
226
等待所有提供的 Futures 完成,并返回已完成值的列表。如果任何 Future 遇到错误,该方法将提前退出并报告错误,不等待其他 Futures 完成。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
227 228 229

参数

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
230
**futures**[*列表*](https://docs.python.org/3/library/stdtypes.html#list "(在 Python v3.12 中)"))- 一个`Future`对象的列表。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
231 232 233

返回值

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
234
已完成的`Future`结果列表。如果任何`Future`上的`wait`抛出错误,此方法将抛出错误。
绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
235 236 237

返回类型

绝不原创的飞龙's avatar
绝不原创的飞龙 已提交
238
[*列表*](https://docs.python.org/3/library/typing.html#typing.List "(在 Python v3.12 中)")