把一个大计算拆成互不依赖的小任务,是理解分布式执行的好起点。Ray 官方的两篇示例都选择了蒙特卡洛估算 π:一篇用任务完成采样、用 Actor 汇总进度;另一篇把相同的计算扩展到大量批次。下面按这个顺序合并译解两篇正文,并说明示例搬到实际环境时需要补上的边界。
来源与版本:Ray documentation contributors / The Ray Team。依据 2026-10-05 读取的 Monte Carlo Estimation of π 与 Using Ray for Highly Parallelizable Tasks;当日页头为 Ray 2.59.0,latest 会继续变化。本文为授权中文翻译与技术整理,新增说明和代码差异均另行标出。未运行 Ray、未压测、未租用算力。

先理解面积比,再考虑并行
在横、纵坐标都落在 −1 到 1 的正方形中均匀随机取点。正方形边长为 2,面积为 4;以原点为圆心、半径为 1 的圆面积为 π。如果某点满足 x² + y² ≤ 1,它就落在圆内。因此,圆内点数占全部点数的比例可以估计 π/4:
π 的估计值 = 4 × 圆内点数 ÷ 总采样数。
每个点的判断都不需要知道其他点的结果,可以把样本分给多个进程或节点。任务返回圆内计数,驱动程序把这些计数相加即可。这个设计减少了任务之间的数据依赖,也不用把所有坐标传回主进程。
原文说增加样本会使结果更接近 π。这里需要补充统计含义:更多独立、均匀样本通常降低估计的不确定性,典型误差规模随样本数的平方根倒数缩小;某一次新计算的数值仍可能比前一次更偏离 π。任务数、CPU 数和小数点后“看起来正确”的位数之间不存在直接保证。
任务返回结果,Actor 保存进度
Ray 的远程任务由普通 Python 函数加上 @ray.remote 定义。调用 sampling_task.remote(...) 会立即返回一个 ObjectRef,真实计算随后由可用 worker 执行。ObjectRef 可以理解为指向将来结果的引用;ray.get(ref) 会等待并取回结果。
Actor 则是保存状态的远程对象。它适合记录“每项采样任务已经处理了多少点”。下面保留官方示例的关键实现,中文注释仅解释原来的行为:
import math
import random
import time
import ray
@ray.remote
class ProgressActor:
def __init__(self, total_num_samples: int):
self.total_num_samples = total_num_samples
self.num_samples_completed_per_task = {}
def report_progress(self, task_id: int, num_samples_completed: int) -> None:
self.num_samples_completed_per_task[task_id] = num_samples_completed
def get_progress(self) -> float:
return sum(self.num_samples_completed_per_task.values()) / self.total_num_samples
@ray.remote
def sampling_task(num_samples: int, task_id: int,
progress_actor: ray.actor.ActorHandle) -> int:
num_inside = 0
for i in range(num_samples):
x, y = random.uniform(-1, 1), random.uniform(-1, 1)
if math.hypot(x, y) <= 1:
num_inside += 1
if (i + 1) % 1_000_000 == 0:
progress_actor.report_progress.remote(task_id, i + 1)
progress_actor.report_progress.remote(task_id, num_samples)
return num_inside
math.hypot(x, y) 求点到原点的距离。任务每处理一百万个样本,异步报告一次累计数量,结束时再报告最终数量。Actor 以任务编号为字典键,覆盖该任务旧的累计计数,而不是把每次报告相加;否则同一任务的中途报告和结束报告会重复计数。
这种进度属于观测状态。多个任务的报告到达时间不同,显示值会滞后于真实执行。若任务重试,计数还可能回退;原示例没有区分重试的 attempt,也没有为 Actor 增加持久恢复逻辑。最终数值应来自成功任务的返回值。
从本地小规模开始提交任务
原文安装提示是 pip install -U ray,其中 -U 会升级到当时可取得的版本。需要复现时应使用独立虚拟环境并记录实际版本,不能把本文读取时的文档版本当作已经安装、验证过的运行环境。
原进度示例默认提交 10 个任务,每个任务采样 10,000,000 次,总计一亿次。下面仅把提交规模改成 4 个任务、每项 100,000 次,并限制本地 Ray 的 CPU 资源声明。它是编辑调整的学习配置,未实测;由于每项不足一百万样本,Actor 通常只收到结束报告,进度会按任务完成阶梯式跳变。
ray.init(num_cpus=2, include_dashboard=False)
NUM_SAMPLING_TASKS = 4
NUM_SAMPLES_PER_TASK = 100_000
TOTAL_NUM_SAMPLES = NUM_SAMPLING_TASKS * NUM_SAMPLES_PER_TASK
progress_actor = ProgressActor.remote(TOTAL_NUM_SAMPLES)
results = [
sampling_task.remote(NUM_SAMPLES_PER_TASK, task_id, progress_actor)
for task_id in range(NUM_SAMPLING_TASKS)
]
ProgressActor.remote(...) 创建并启动 Actor,返回句柄;这个句柄作为参数传给每个任务。任务数并不等于同时运行的数量:Ray 会根据可用资源调度。小任务拆得过细时,调度、序列化和通信开销可能比采样计算还显著;拆得过大则不利于负载均衡和观察中途进度。
等待结束时,也要检查任务是否失败
官方原循环每秒查询一次 Actor,直到 progress == 1,然后才调用 ray.get(results)。如果某项任务永久失败、没有报告最终数量,这个循环可能一直等待,任务异常也不会及时通过结果读取暴露出来。若 Actor 丢失或查询无法及时完成,纯进度等待同样缺少边界。
以下是编辑提供的替换循环:用 ray.wait 收集已就绪引用,立即读取结果以传播异常,同时给整体等待和 Actor 查询设置期限。60 秒只是示范预算,不代表此规模应在 60 秒内完成。它保留原算法,改变了驱动端的终止判据和失败处理;未执行测试。
pending = list(results)
total_num_inside = 0
deadline = time.monotonic() + 60
try:
while pending:
if time.monotonic() >= deadline:
raise TimeoutError("Sampling exceeded the demonstration deadline")
ready, pending = ray.wait(pending, num_returns=1, timeout=1.0)
for ref in ready:
total_num_inside += ray.get(ref)
progress = ray.get(progress_actor.get_progress.remote(), timeout=5.0)
print(f"Reported progress: {progress:.0%}")
pi_estimate = 4 * total_num_inside / TOTAL_NUM_SAMPLES
print(f"Estimated pi: {pi_estimate}")
except Exception:
for ref in results:
ray.cancel(ref, force=False)
raise
finally:
ray.shutdown()
这里的取消请求不是事务回滚,也不保证所有远端工作瞬间停止。ray.shutdown() 用于释放本次本地会话;不要把它当作管理任意共享生产集群的方案。即使任务结果全部返回,最后一次 Actor 报告仍可能正在传递,因此报告值短暂低于 100% 也不影响按返回计数计算结果。
原文示例最后输出 3.1412202,仅表示官方展示的一次结果。本文没有生成新的估计值,也没有把原文输出冒充本次测试日志。
另一种写法:把 π/4 作为每批结果
第二篇官方教程从一个“相同算法处理很多独立输入”的场景引入并行:十万个任务若各需一分钟,单处理器需要约 70 天;更多处理器可以分摊工作。原文的这些估算用来说明规模关系,实际完成时间还受调度、数据传输、资源争用和任务分布影响。
它的采样区域改为 [0, 1) × [0, 1),统计单位圆第一象限的四分之一圆。面积比仍然是 π/4。每个任务返回 Fraction(in_count, sample_count),用分数保存本批比例:
from fractions import Fraction
@ray.remote
def pi4_sample(sample_count):
in_count = 0
for _ in range(sample_count):
x = random.random()
y = random.random()
if x * x + y * y <= 1:
in_count += 1
return Fraction(in_count, sample_count)
原文先对一百万个样本计时并取回结果,然后把工作扩大到一千亿个样本,每批一百万个,总计十万项任务。所有远程调用先放进列表,最后一次 ray.get(results) 等待结果,从而避免在提交循环内逐项阻塞。每批样本数量相等时,sum(output) * 4 / len(output) 就是整体估计;若批次大小不同,需要按样本数加权,直接平均各批比例会改变估计权重。
这组十万任务、一千亿采样的参数不适合作为个人电脑默认值。驱动端会保存大量引用,调度系统也会承受集中提交的压力。扩展时应限制在途任务数、分批提交和收集,并根据集群资源确定每批粒度。该教程使用 ray.init(address="auto"),前提是已经建立 Ray 集群,并在能连接该集群的环境中运行;它不是“自动为你创建任意规模集群”。
原文给出过一次一百万采样约 1.49 秒的输出,后文又以单核每批约 0.4 秒估算约 11 小时,并展示 168 个核心工作的 Dashboard 与约 80% 效率。不同示例上下文不能直接拼成可复现的性能承诺。它展示的估计值 3.14159518188 和约 8.05 × 10⁻⁷ 的相对偏差,也只属于原作者的那次计算。本文使用原创流程图,没有制作或修改性能截图。
静态代码审查与适用范围
本次已逐段审查两个示例的导入、远程调用、随机采样、进度汇总和结果聚合,没有在这些代码段中发现硬编码秘密、命令注入或文件删除操作。发现的实际问题是:较大的默认计算规模;依靠进度值无限等待;缺少重试状态区分和 Actor 恢复;高并行版集中提交十万任务;以及性能数字容易被脱离上下文引用。前文已分别解释,并明确标注改动。
Ray 集群可以执行提交的 Python 代码,因此只能连接自己有权使用的可信环境,不能把示例端口和控制接口随意暴露给不可信网络。本次没有启动任何集群,也没有验证操作系统、依赖或集群安全配置。静态未发现某类问题不等于代码或部署环境不存在漏洞。
归属与许可:原文版权 © 2026 The Ray Team;项目源码许可证为 Apache License 2.0,相关 Apache License 2.0 及 Ray Authors 版权声明见本文下方。中文译解、图示、较小参数和带期限的等待循环为本次编辑新增。保留原作者、来源和适用许可声明。
Ray 示例代码 Apache License 2.0
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023 Ray Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.












暂无评论内容