[Feature] Unify transport selection for inference services#3958
Open
vmoens wants to merge 3 commits into
Open
Conversation
Give inference services one configurable story for moving payloads independently of where the service owner runs: service_backend (and the collector backend/policy_backend spellings) chooses placement, transport chooses how payloads move, and .client() hides both from consumer code. Changes: - Add TransportKind, TransportConfig, normalization helpers, and a per-domain transport-resolver registry in torchrl._comm.transport (re-exported from torchrl._comm and torchrl.services). There is deliberately no common transport implementation ABC: queues, shared memory, object stores, and collectives keep their own semantics. - Add make_inference_transport, a public resolver for the inference request/reply domain that accepts None/"auto", a kind string, a TransportConfig, or a concrete InferenceTransport, plus topology context (policy_backend, num_slots, request/response specs). "auto" deterministically picks the fastest safe transport: per-producer slots for threads, shared-memory TensorDict slots for process actors with a static payload contract, plain queues otherwise, and the Ray/Monarch transports for their topologies. Incompatible forced choices raise instead of silently degrading. - Accept string/config transport choices (plus transport_options) in InferenceServer, ProcessInferenceServer, and AsyncBatchedCollector, replacing the private collector transport factory. The resolved choice is inspectable through the new transport_kind and transport_config properties; inference_transport_kind reports the kind of injected instances too. - Document the placement/transport separation and auto resolution rules in the inference-server reference. Existing spellings are preserved: backend/env_backend/policy_backend keep their meaning, concrete transport injection is unchanged, and default resolution is behavior-compatible (threading -> SlotTransport, multiprocessing -> MPTransport unless specs enable shared memory). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/rl/3958
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit af64a0f with merge base 2a0c554 ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
Contributor
Benchmark Results: PR
|
| Benchmark | main ops | PR ops | Change |
|---|---|---|---|
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictPrioritizedReplayBuffer-ListStorage-None-400] |
188.36 | 54.90 | -70.85% |
benchmarks/test_objectives_benchmarks.py::test_redq_deprec_speed[False-None] |
62.06 | 89.33 | +43.93% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyTensorStorage-RandomSampler-400] |
862.98 | 1,122 | +30.00% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-ListStorage-RandomSampler-400] |
48.18 | 36.91 | -23.40% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[vec_generalized_advantage_estimate-True-32-512] |
28.96 | 34.44 | +18.92% |
benchmarks/test_envs_benchmark.py::test_cat_frames_functional[4-same] |
2,840 | 2,448 | -13.81% |
benchmarks/test_objectives_benchmarks.py::test_dqn_speed[True-backward] |
894.31 | 1,018 | +13.81% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictPrioritizedReplayBuffer-LazyMemmapStorage-None-400] |
510.96 | 448.42 | -12.24% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictPrioritizedReplayBuffer-LazyTensorStorage-None-10000] |
2,090 | 2,331 | +11.53% |
benchmarks/test_collectors_benchmark.py::test_single_with_rb |
7.3545 | 6.5083 | -11.51% |
benchmarks/test_objectives_benchmarks.py::test_redq_deprec_speed[True-backward] |
127.67 | 139.79 | +9.49% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-256-256-64] |
9.2013 | 8.3636 | -9.10% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyTensorStorage-RandomSampler-10000] |
3,299 | 3,001 | -9.04% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictPrioritizedReplayBuffer-LazyMemmapStorage-None-10000] |
1,971 | 2,130 | +8.05% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyMemmapStorage-RandomSampler-400] |
553.16 | 508.93 | -8.00% |
benchmarks/test_objectives_benchmarks.py::test_redq_deprec_speed[reduce-overhead-None] |
262.52 | 282.09 | +7.45% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyMemmapStorage-RandomSampler-10000] |
3,233 | 3,038 | -6.06% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyTensorStorage-SamplerWithoutReplacement-10000] |
3,088 | 3,271 | +5.92% |
benchmarks/test_objectives_benchmarks.py::test_values[generalized_advantage_estimate-True-True] |
96.67 | 90.98 | -5.89% |
benchmarks/test_non_tensor_env_benchmark.py::test_non_tensor_env_rollout_speed[1000-parallel-buffers-True] |
0.4962 | 0.5246 | +5.73% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictPrioritizedReplayBuffer-LazyTensorStorage-None-10000] |
2,181 | 2,299 | +5.42% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_stack_then_write[100-img_shape1-atari] |
263.17 | 277.41 | +5.41% |
benchmarks/test_objectives_benchmarks.py::test_values[td0_return_estimate-False-False] |
7,482 | 7,879 | +5.30% |
benchmarks/test_objectives_benchmarks.py::test_redq_deprec_speed[True-None] |
261.58 | 275.39 | +5.28% |
benchmarks/test_envs_benchmark.py::test_simple |
1.8044 | 1.7105 | -5.21% |
benchmarks/test_objectives_benchmarks.py::test_iql_speed[True-None] |
113.69 | 119.57 | +5.17% |
benchmarks/test_objectives_benchmarks.py::test_a2c_speed[True-backward] |
116.40 | 122.39 | +5.15% |
benchmarks/test_compressed_storage_benchmark.py::TestCompressedStorageBenchmark::test_tensor_to_bytestream_speed[safetensors] |
22,800 | 23,972 | +5.14% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyMemmapStorage-SamplerWithoutReplacement-400] |
524.53 | 551.35 | +5.11% |
benchmarks/test_objectives_benchmarks.py::test_a2c_speed[True-None] |
276.98 | 291.13 | +5.11% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[True-None] |
327.89 | 344.47 | +5.05% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[True-backward] |
122.27 | 128.30 | +4.93% |
benchmarks/test_objectives_benchmarks.py::test_iql_speed[True-backward] |
58.58 | 61.45 | +4.89% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyMemmapStorage-RandomSampler-10000] |
2,917 | 2,776 | -4.85% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-False-False-False] |
46,551 | 44,311 | -4.81% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-480-640-64] |
5.9519 | 5.6827 | -4.52% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictPrioritizedReplayBuffer-LazyTensorStorage-None-400] |
889.48 | 929.48 | +4.50% |
benchmarks/test_envs_benchmark.py::test_transformed |
0.9056 | 0.8659 | -4.38% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictPrioritizedReplayBuffer-LazyMemmapStorage-None-10000] |
1,987 | 2,071 | +4.20% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_stack_then_write[100-img_shape2-large_img] |
174.12 | 167.15 | -4.00% |
benchmarks/test_objectives_benchmarks.py::test_ddpg_speed[True-backward] |
408.79 | 424.66 | +3.88% |
benchmarks/test_objectives_benchmarks.py::test_ppo_speed[reduce-overhead-None] |
258.11 | 267.99 | +3.83% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[generalized_advantage_estimate-False-1-512] |
108.23 | 112.30 | +3.76% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-224-224-64] |
11.19 | 10.77 | -3.72% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyTensorStorage-SamplerWithoutReplacement-400] |
1,038 | 1,074 | +3.49% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-True-False-False] |
78,538 | 75,806 | -3.48% |
benchmarks/test_objectives_benchmarks.py::test_dqn_speed[True-None] |
1,786 | 1,724 | -3.43% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[False-None] |
210.58 | 217.71 | +3.39% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[100-img_shape1-atari] |
699.59 | 722.05 | +3.21% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_lazystack_then_write[100-img_shape1-atari] |
642.45 | 662.86 | +3.18% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-224-224-64] |
4.4789 | 4.6170 | +3.08% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[vec_generalized_advantage_estimate-True-1-512] |
643.97 | 663.62 | +3.05% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_extend_sample[ReplayBuffer-LazyTensorStorage-RandomSampler-10000-10000-100-True] |
25.19 | 25.95 | +3.02% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-256-256-1] |
489.02 | 503.80 | +3.02% |
benchmarks/test_objectives_benchmarks.py::test_a2c_speed[False-backward] |
81.84 | 84.30 | +3.01% |
benchmarks/test_objectives_benchmarks.py::test_values[td_lambda_return_estimate-True-False] |
24.54 | 25.27 | +3.00% |
benchmarks/test_objectives_benchmarks.py::test_redq_deprec_speed[False-backward] |
64.61 | 62.67 | -3.00% |
benchmarks/test_objectives_benchmarks.py::test_iql_speed[reduce-overhead-None] |
115.75 | 119.21 | +2.99% |
benchmarks/test_envs_benchmark.py::test_cat_frames_functional[16-same] |
1,854 | 1,909 | +2.97% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[reduce-overhead-None] |
332.31 | 341.69 | +2.82% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-224-224-16] |
47.76 | 49.10 | +2.79% |
benchmarks/test_objectives_benchmarks.py::test_a2c_speed[reduce-overhead-None] |
283.41 | 291.14 | +2.73% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[vec_generalized_advantage_estimate-False-32-512] |
552.25 | 566.83 | +2.64% |
benchmarks/test_objectives_benchmarks.py::test_iql_speed[False-None] |
49.52 | 50.83 | +2.63% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyTensorStorage-SamplerWithoutReplacement-10000] |
3,564 | 3,471 | -2.62% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[100-img_shape2-large_img] |
405.09 | 415.71 | +2.62% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-True-False-True] |
39,127 | 38,136 | -2.53% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-224-224-1] |
282.49 | 275.56 | -2.46% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[200-img_shape3-large_batch] |
329.72 | 337.70 | +2.42% |
benchmarks/test_objectives_benchmarks.py::test_td3_speed[True-backward] |
284.47 | 291.35 | +2.42% |
benchmarks/test_envs_benchmark.py::test_parallel |
0.9569 | 0.9338 | -2.42% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-False-False-False] |
64,979 | 63,429 | -2.39% |
benchmarks/test_replaybuffer_benchmark.py::TestWindowingTransformsBenchmark::test_action_chunk_transform[no_done] |
1,582 | 1,619 | +2.38% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-224-224-16] |
18.01 | 18.43 | +2.36% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-True-False] |
32,223 | 31,475 | -2.32% |
benchmarks/test_objectives_benchmarks.py::test_cql_speed[True-backward] |
58.02 | 59.35 | +2.29% |
benchmarks/test_replaybuffer_benchmark.py::TestWindowingTransformsBenchmark::test_catframes_offline |
529.35 | 541.33 | +2.26% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[False-backward] |
131.75 | 134.70 | +2.24% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-256-256-4] |
48.49 | 49.57 | +2.24% |
benchmarks/test_collectors_benchmark.py::test_sync_preempt |
16.14 | 16.50 | +2.24% |
benchmarks/test_compressed_storage_benchmark.py::TestCompressedStorageBenchmark::test_tensor_to_bytestream_speed[untyped_storage] |
8.2890 | 8.1044 | -2.23% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_lazystack_then_write[50-img_shape0-small] |
3,515 | 3,593 | +2.22% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyMemmapStorage-SamplerWithoutReplacement-10000] |
3,414 | 3,489 | +2.22% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-True-True] |
20,029 | 19,591 | -2.19% |
benchmarks/test_replaybuffer_benchmark.py::test_replay_buffer_direct_client_identity |
8,100,540 | 7,927,533 | -2.14% |
benchmarks/test_objectives_benchmarks.py::test_cql_speed[reduce-overhead-None] |
83.15 | 84.92 | +2.12% |
benchmarks/test_objectives_benchmarks.py::test_ppo_speed[True-None] |
259.49 | 264.85 | +2.07% |
benchmarks/test_replaybuffer_benchmark.py::TestPrioritizedReplayBufferBenchmark::test_sample_mixed_devices[1000000-memmap_cpu_storage_cpu... |
75.23 | 76.76 | +2.03% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[50-img_shape0-small] |
4,418 | 4,507 | +2.03% |
benchmarks/test_replaybuffer_benchmark.py::TestPrioritizedReplayBufferBenchmark::test_sampler_sample_scale[10000000-cpu] |
50.47 | 51.49 | +2.01% |
benchmarks/test_storage_write_benchmark.py::TestCollectorIntegrationBenchmark::test_collector_without_rb[100-img_shape0-atari] |
29.32 | 29.90 | +1.99% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-224-224-4] |
71.80 | 73.20 | +1.95% |
benchmarks/test_objectives_benchmarks.py::test_dqn_speed[reduce-overhead-None] |
1,797 | 1,832 | +1.94% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-224-224-1] |
620.26 | 632.30 | +1.94% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-256-256-16] |
42.01 | 42.82 | +1.93% |
benchmarks/test_envs_benchmark.py::test_serial |
0.5727 | 0.5837 | +1.93% |
benchmarks/test_objectives_benchmarks.py::test_a2c_speed[False-None] |
176.23 | 179.60 | +1.91% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-256-256-16] |
12.20 | 12.43 | +1.89% |
benchmarks/test_objectives_benchmarks.py::test_cql_speed[True-None] |
83.72 | 85.29 | +1.88% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_extend_sample[ReplayBuffer-LazyTensorStorage-RandomSampler-1000000-10000-100-True] |
23.58 | 24.01 | +1.83% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-False-True] |
33,532 | 32,921 | -1.82% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-True-False-True] |
42,859 | 42,085 | -1.80% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-True-True-False-False] |
56,639 | 57,650 | +1.79% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-256-256-1] |
192.54 | 195.94 | +1.77% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-True-True-False] |
28,838 | 29,333 | +1.72% |
benchmarks/test_rnn_reset_backends_benchmark.py::test_rnn_rollout_with_intermediate_resets[b256-t128-i32-h512-scan-False-0-gru] |
2.9658 | 3.0166 | +1.71% |
benchmarks/test_objectives_benchmarks.py::test_ddpg_speed[False-None] |
341.27 | 346.95 | +1.67% |
benchmarks/test_objectives_benchmarks.py::test_ppo_speed[True-backward] |
114.96 | 116.88 | +1.67% |
benchmarks/test_objectives_benchmarks.py::test_sac_speed[True-backward] |
250.54 | 254.63 | +1.64% |
benchmarks/test_objectives_benchmarks.py::test_cql_speed[False-backward] |
28.29 | 27.83 | -1.62% |
benchmarks/test_collectors_benchmark.py::test_single |
8.7992 | 8.9378 | +1.58% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-ListStorage-SamplerWithoutReplacement-4000] |
168.36 | 165.71 | -1.57% |
benchmarks/test_objectives_benchmarks.py::test_values[td1_return_estimate-False-False] |
36.45 | 37.02 | +1.57% |
benchmarks/test_objectives_benchmarks.py::test_td3_speed[True-None] |
559.78 | 568.51 | +1.56% |
benchmarks/test_objectives_benchmarks.py::test_ppo_speed[False-backward] |
77.47 | 78.68 | +1.56% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-True-True-True] |
24,204 | 23,828 | -1.55% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_lazystack_then_write[200-img_shape3-large_batch] |
309.49 | 314.26 | +1.54% |
benchmarks/test_storage_write_benchmark.py::TestCollectorIntegrationBenchmark::test_collector_without_rb[200-img_shape1-large_batch] |
14.97 | 15.19 | +1.52% |
benchmarks/test_objectives_benchmarks.py::test_ddpg_speed[False-backward] |
242.16 | 245.82 | +1.51% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-256-256-64] |
3.0529 | 3.0983 | +1.49% |
| ... | ... | ... | Showing 120 of 220 comparisons, sorted by absolute change. |
GPU
Compared 230 benchmarks. Regressions over 5%: 13. Improvements over 5%: 13.
| Benchmark | main ops | PR ops | Change |
|---|---|---|---|
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-ListStorage-SamplerWithoutReplacement-400] |
42.09 | 195.18 | +363.78% |
benchmarks/test_objectives_benchmarks.py::test_sac_speed[False-None] |
83.16 | 115.44 | +38.82% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyTensorStorage-RandomSampler-10000] |
3,463 | 2,512 | -27.48% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyTensorStorage-SamplerWithoutReplacement-10000] |
3,695 | 2,816 | -23.77% |
benchmarks/test_objectives_benchmarks.py::test_iql_speed[reduce-overhead-None] |
104.12 | 81.47 | -21.75% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyTensorStorage-SamplerWithoutReplacement-400] |
816.06 | 989.53 | +21.26% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyMemmapStorage-RandomSampler-10000] |
2,543 | 3,045 | +19.75% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyMemmapStorage-RandomSampler-10000] |
3,275 | 2,665 | -18.62% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictPrioritizedReplayBuffer-LazyMemmapStorage-None-10000] |
1,831 | 2,169 | +18.47% |
benchmarks/test_objectives_benchmarks.py::test_sac_speed[reduce-overhead-None] |
120.25 | 100.32 | -16.57% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyMemmapStorage-SamplerWithoutReplacement-10000] |
3,391 | 2,898 | -14.55% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyMemmapStorage-RandomSampler-400] |
474.20 | 526.16 | +10.96% |
benchmarks/test_objectives_benchmarks.py::test_dqn_speed[True-backward] |
1,014 | 915.24 | -9.73% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-LazyTensorStorage-SamplerWithoutReplacement-10000] |
2,721 | 2,961 | +8.79% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyTensorStorage-RandomSampler-10000] |
2,716 | 2,907 | +7.01% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictPrioritizedReplayBuffer-LazyMemmapStorage-None-400] |
489.82 | 455.93 | -6.92% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyMemmapStorage-sampler6-10000] |
791.93 | 738.86 | -6.70% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[generalized_advantage_estimate-False-1-512] |
50.40 | 47.14 | -6.47% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_stack_then_write[200-img_shape3-large_batch] |
134.69 | 142.86 | +6.07% |
benchmarks/test_envs_benchmark.py::test_simple |
1.2808 | 1.2076 | -5.72% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-LazyMemmapStorage-SamplerWithoutReplacement-400] |
501.15 | 473.24 | -5.57% |
benchmarks/test_compressed_storage_benchmark.py::TestCompressedStorageBenchmark::test_tensor_to_bytestream_speed[safetensors] |
24,851 | 23,472 | -5.55% |
benchmarks/test_replaybuffer_benchmark.py::TestPrioritizedReplayBufferBenchmark::test_sample_mixed_devices[1000000-cuda_storage_cpu_sampler] |
83.79 | 88.37 | +5.46% |
benchmarks/test_objectives_benchmarks.py::test_dqn_speed[True-None] |
1,919 | 2,023 | +5.41% |
benchmarks/test_envs_benchmark.py::test_cat_frames_functional[16-same] |
3,561 | 3,743 | +5.12% |
benchmarks/test_envs_benchmark.py::test_cat_frames_functional[16-constant] |
4,727 | 4,964 | +5.03% |
benchmarks/test_objectives_benchmarks.py::test_td3_speed[True-None] |
734.64 | 771.25 | +4.98% |
benchmarks/test_replaybuffer_benchmark.py::TestWindowingTransformsBenchmark::test_action_chunk_transform[done_aware] |
1,519 | 1,595 | +4.96% |
benchmarks/test_non_tensor_env_benchmark.py::test_non_tensor_env_rollout_speed[1000-single-True] |
1.3273 | 1.3928 | +4.93% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-False-False-True] |
38,296 | 40,152 | +4.85% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[100-img_shape1-atari] |
698.35 | 664.59 | -4.83% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[vec_generalized_advantage_estimate-False-1-512] |
1,399 | 1,333 | -4.74% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_lazystack_then_write[100-img_shape2-large_img] |
409.09 | 389.95 | -4.68% |
benchmarks/test_objectives_benchmarks.py::test_sac_speed[True-backward] |
349.13 | 332.94 | -4.64% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-False-False] |
55,714 | 58,276 | +4.60% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-False-True] |
33,588 | 35,048 | +4.35% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-224-224-1] |
581.38 | 606.08 | +4.25% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-224-224-4] |
69.77 | 72.73 | +4.24% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-False-True-False] |
27,135 | 28,280 | +4.22% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-True-True-True] |
20,963 | 21,840 | +4.18% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-True-False] |
32,003 | 33,341 | +4.18% |
benchmarks/test_compressed_storage_benchmark.py::TestCompressedStorageBenchmark::test_tensor_to_bytestream_speed[torch.save] |
7,055 | 7,345 | +4.11% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictReplayBuffer-LazyMemmapStorage-SamplerWithoutReplacement-10000] |
3,471 | 3,331 | -4.03% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-True-False-False] |
64,674 | 67,248 | +3.98% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-True-True-False] |
34,932 | 36,318 | +3.97% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[50-img_shape0-small] |
4,355 | 4,183 | -3.95% |
benchmarks/test_replaybuffer_benchmark.py::TestPrioritizedReplayBufferBenchmark::test_sample_mixed_devices[1000000-memmap_cpu_storage_cud... |
995.93 | 956.69 | -3.94% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-False-True-True] |
19,789 | 20,569 | +3.94% |
benchmarks/test_collectors_benchmark.py::test_single |
6.9125 | 6.6448 | -3.87% |
benchmarks/test_objectives_benchmarks.py::test_dqn_speed[reduce-overhead-None] |
1,885 | 1,958 | +3.84% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_contiguous[100-img_shape2-large_img] |
565.49 | 543.77 | -3.84% |
benchmarks/test_objectives_benchmarks.py::test_td3_speed[True-backward] |
405.44 | 390.08 | -3.79% |
benchmarks/test_replaybuffer_benchmark.py::TestWindowingTransformsBenchmark::test_action_chunk_transform[no_done] |
1,581 | 1,640 | +3.72% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-True-False-True-False] |
32,249 | 33,447 | +3.72% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-True-False-True] |
31,495 | 30,325 | -3.71% |
benchmarks/test_replaybuffer_benchmark.py::TestPrioritizedReplayBufferBenchmark::test_sampler_sample_scale[1000000-cuda] |
2,330 | 2,246 | -3.62% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictPrioritizedReplayBuffer-LazyTensorStorage-None-400] |
809.22 | 838.38 | +3.60% |
benchmarks/test_rnn_reset_backends_benchmark.py::test_rnn_rollout_with_intermediate_resets[b256-t128-i32-h512-scan-False-0-lstm] |
21.62 | 22.35 | +3.36% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[True-backward] |
357.52 | 369.47 | +3.34% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-True-True-True-False] |
34,566 | 35,705 | +3.29% |
benchmarks/test_envs_benchmark.py::test_cat_frames_functional[4-constant] |
4,858 | 5,017 | +3.28% |
benchmarks/test_replaybuffer_benchmark.py::TestPrioritizedReplayBufferBenchmark::test_sample_mixed_devices[1000000-cuda_storage_cuda_samp... |
1,553 | 1,502 | -3.27% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-256-256-1] |
188.28 | 194.40 | +3.25% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-False-True-True] |
17,927 | 18,494 | +3.16% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_lazystack[100-img_shape2-large_img] |
420.71 | 408.05 | -3.01% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-224-224-16] |
17.62 | 18.14 | +2.95% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-False-True-False-True] |
37,779 | 38,882 | +2.92% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-False-True-True] |
22,086 | 22,719 | +2.86% |
benchmarks/test_objectives_benchmarks.py::test_ddpg_speed[False-backward] |
249.15 | 242.05 | -2.85% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_sample[TensorDictPrioritizedReplayBuffer-LazyMemmapStorage-None-10000] |
1,956 | 2,011 | +2.83% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-224-224-4] |
178.72 | 183.67 | +2.77% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-True-True-False] |
29,851 | 30,678 | +2.77% |
benchmarks/test_objectives_benchmarks.py::test_a2c_speed[False-backward] |
155.79 | 151.69 | -2.63% |
benchmarks/test_replaybuffer_benchmark.py::test_replay_buffer_direct_client_identity |
7,962,244 | 8,171,414 | +2.63% |
benchmarks/test_objectives_benchmarks.py::test_values[vec_generalized_advantage_estimate-True-True] |
462.16 | 474.12 | +2.59% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[False-backward] |
289.08 | 281.63 | -2.58% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-480-640-1] |
465.22 | 453.29 | -2.56% |
benchmarks/test_objectives_benchmarks.py::test_gae_speed[vec_generalized_advantage_estimate-False-32-512] |
1,366 | 1,331 | -2.56% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-True-False-True-True] |
19,775 | 20,282 | +2.56% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_contiguous[200-img_shape3-large_batch] |
721.58 | 740.02 | +2.56% |
benchmarks/test_rnn_reset_backends_benchmark.py::test_rnn_rollout_with_intermediate_resets[b256-t128-i32-h512-scan-True-0-gru] |
52.96 | 51.61 | -2.54% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-True-False-False] |
50,698 | 51,973 | +2.52% |
benchmarks/test_objectives_benchmarks.py::test_iql_speed[True-backward] |
254.56 | 248.23 | -2.49% |
benchmarks/test_replaybuffer_benchmark.py::TestWindowingTransformsBenchmark::test_catframes_offline |
568.02 | 554.30 | -2.42% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-480-640-16] |
35.33 | 36.17 | +2.40% |
benchmarks/test_envs_benchmark.py::test_parallel |
0.5460 | 0.5585 | +2.30% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_stack_then_write[100-img_shape2-large_img] |
171.51 | 175.31 | +2.22% |
benchmarks/test_storage_write_benchmark.py::TestCollectorIntegrationBenchmark::test_collector_with_rb_cuda[100-img_shape0-atari] |
13.76 | 13.47 | -2.15% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[True-True-False-False-False] |
64,707 | 66,098 | +2.15% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-True-True-False-False] |
57,988 | 59,208 | +2.10% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_stack_then_write[50-img_shape0-small] |
903.96 | 885.19 | -2.08% |
benchmarks/test_envs_benchmark.py::test_transformed |
0.7302 | 0.7155 | -2.02% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-True-False-False-False] |
50,898 | 51,924 | +2.02% |
benchmarks/test_objectives_benchmarks.py::test_values[vec_td1_return_estimate-False-False] |
866.94 | 849.86 | -1.97% |
benchmarks/test_objectives_benchmarks.py::test_cql_speed[True-backward] |
229.01 | 233.40 | +1.92% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-256-256-16] |
41.50 | 42.28 | +1.88% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_lazystack_then_write[50-img_shape0-small] |
3,553 | 3,489 | -1.81% |
benchmarks/test_storage_write_benchmark.py::TestCollectorIntegrationBenchmark::test_collector_with_rb[100-img_shape0-atari] |
20.93 | 20.55 | -1.80% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_storage_write_contiguous[50-img_shape0-small] |
6,142 | 6,034 | -1.76% |
benchmarks/test_objectives_benchmarks.py::test_redq_deprec_speed[True-None] |
441.01 | 433.38 | -1.73% |
benchmarks/test_rnn_reset_backends_benchmark.py::test_rnn_rollout_with_intermediate_resets[b256-t128-i32-h512-scan-True-0-lstm] |
82.53 | 81.10 | -1.72% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[torchvision-480-640-64] |
6.9127 | 7.0309 | +1.71% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_extend_sample[ReplayBuffer-LazyTensorStorage-RandomSampler-1000000-10000-100-False] |
47.64 | 48.45 | +1.69% |
benchmarks/test_objectives_benchmarks.py::test_ddpg_speed[reduce-overhead-None] |
839.53 | 853.63 | +1.68% |
benchmarks/test_objectives_benchmarks.py::test_values[td_lambda_return_estimate-True-False] |
11.83 | 12.03 | +1.67% |
benchmarks/test_objectives_benchmarks.py::test_ppo_speed[True-None] |
716.88 | 728.76 | +1.66% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_extend_sample[ReplayBuffer-LazyTensorStorage-RandomSampler-10000-10000-100-False] |
53.20 | 52.33 | -1.65% |
benchmarks/test_objectives_benchmarks.py::test_ddpg_speed[True-backward] |
462.46 | 470.05 | +1.64% |
benchmarks/test_collectors_benchmark.py::test_single_with_rb_pixels |
5.3740 | 5.2860 | -1.64% |
benchmarks/test_storage_write_benchmark.py::TestCollectorIntegrationBenchmark::test_collector_without_rb[200-img_shape1-large_batch] |
15.09 | 14.85 | -1.61% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-480-640-1] |
79.70 | 80.96 | +1.59% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_populate[TensorDictReplayBuffer-ListStorage-RandomSampler-400] |
194.93 | 197.96 | +1.55% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-480-640-4] |
19.86 | 20.17 | +1.55% |
benchmarks/test_vla_preprocessing_benchmark.py::test_openvla_preprocessing_throughput[pil-480-640-64] |
1.2489 | 1.2680 | +1.53% |
benchmarks/test_envs_benchmark.py::test_step_mdp_speed[False-False-True-True-True] |
18,694 | 18,978 | +1.52% |
benchmarks/test_objectives_benchmarks.py::test_reinforce_speed[reduce-overhead-None] |
122.42 | 120.57 | -1.51% |
benchmarks/test_storage_write_benchmark.py::TestCollectorIntegrationBenchmark::test_collector_with_rb_cuda[200-img_shape1-large_batch] |
6.8968 | 6.7935 | -1.50% |
benchmarks/test_replaybuffer_benchmark.py::test_rb_iterate[TensorDictReplayBuffer-ListStorage-RandomSampler-4000] |
170.97 | 173.52 | +1.49% |
benchmarks/test_storage_write_benchmark.py::TestStorageWriteBenchmark::test_collector_lazystack_then_write[200-img_shape3-large_batch] |
299.56 | 303.96 | +1.47% |
benchmarks/test_rnn_reset_backends_benchmark.py::test_rnn_rollout_with_intermediate_resets[b256-t128-i32-h512-scan-False-0-gru] |
23.20 | 23.54 | +1.46% |
| ... | ... | ... | Showing 120 of 230 comparisons, sorted by absolute change. |
Support the ray + distributed combination: Ray (or any remote-process) actors moving inference payloads through torch.distributed point-to-point ops instead of object-store serialization. DistributedTransport gives every server/client pair standalone ProcessGroupGloo (and, for CUDA payloads, ProcessGroupNCCL) groups rendezvoused through a transport-owned TCPStore, so the default process group stays free for training collectives. Small headers and pickled exceptions ride gloo control pairs; fixed-spec tensor payloads ride gloo (CPU) or NCCL (GPU-direct) data pairs, with NCCL receives posted only after a header announces them so idle receives never trip the NCCL watchdog and each communicator stays single-threaded. Clients are picklable and connect lazily inside the actor process; the server discovers clients through the store, so client creation is not ordered with respect to server startup. Blocking receiver threads feed in-process queues on both sides (gloo Work.is_completed() does not report completion for receives, so irecv-polling designs do not work). The resolver maps transport="distributed" to this transport for any non-thread actor topology (requires request/response specs; never chosen by "auto"), and inference_transport_kind reports it. Tests cover in-process, spawned cross-process, and Ray-actor clients, out-of-order futures, exception propagation, nested keys, timeout semantics, and spec validation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Address the CodeQL finding on the free-port probe: bind the probe socket to the advertised host instead of the wildcard address, which also validates early that the host is a local interface. Document the actual security posture in the class docstring: like all of torch.distributed, the rendezvous TCPStore accepts unauthenticated connections on all interfaces regardless of the host argument, control headers and exception payloads are pickled, and the payload channels are unencrypted, so the transport must only be deployed on trusted, isolated networks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Gives inference services one clear, configurable story for moving payloads independently of where the service owner runs:
service_backend(and the stable collectorbackend/policy_backendspellings) chooses ownership and placement;transportchooses how payloads move ("queue","shared_memory","distributed","ray","monarch", or"auto");.client()hides both choices from consumer code.Follow-up to #3955 (
SharedMemoryTransport), which this PR wires into collector/server-level selection.What's included
Common configuration envelope (
torchrl._comm.transport, re-exported fromtorchrl._commandtorchrl.services):TransportKindliteral, frozenTransportConfig(kind, options)dataclass,normalize_transport_kind/as_transport_configvalidation helpers, and a per-domain transport-resolver registry (register_transport_resolver/resolve_transport). Deliberately no common transport implementation ABC: queues, shared memory, object stores, and collectives have different semantics; domains register a resolver instead.Public inference transport resolution (
make_inference_transport):None/"auto", a kind string, aTransportConfig, or a concreteInferenceTransport(returned unchanged), plus topology context (policy_backend,num_slots,request_spec/response_spec,transport_options)."auto"resolves deterministically: thread actors with a known slot count getSlotTransport; process actors with a static TensorDict contract getSharedMemoryTransport; process actors otherwise getMPTransport; Ray/Monarch topologies get their transports. Partial specs and incompatible forced combinations raise with actionable messages instead of silently degrading. The resolution is logged at debug level.DistributedTransport(new): placement and payload movement compose independently — in particular Ray placement + torch.distributed payloads:backend="gloo"moves CPU tensors;backend="nccl"moves CUDA tensors GPU-direct with no host round trip.ProcessGroupGloo/ProcessGroupNCCLobjects rendezvoused through a transport-ownedTCPStore— the default process group is never touched, so training code keepsinit_process_groupfor its own collectives.Work.is_completed()does not report completion for receives, so irecv-polling designs do not work — verified empirically).transport="distributed"for any non-thread actor topology; never chosen by"auto"(it needs a static payload contract and a rendezvous).Wiring:
AsyncBatchedCollector,InferenceServer, andProcessInferenceServeraccept string/configtransportchoices plustransport_options; the collector's private_make_transportfactory is replaced by the public resolver (num_slotsdefaults to the number of envs).ProcessInferenceServerresolves with amultiprocessingtopology, sotransport="auto"+ specs gives the shared-memory fast path with zero extra plumbing.transport_kind(derived from the concrete instance, so injected transports report too; unknown classes report"custom") andtransport_config(Nonewhen an instance was injected) on all three classes.Compatibility
backend/env_backend/policy_backendspellings unchanged;service_backendkeeps placement semantics.transport=MPTransport(...)etc. still works everywhere).SlotTransport(num_envs), multiprocessing ->MPTransport()unless specs enable shared memory, ray/monarch unchanged.Tests
Extends
test/test_inference_server.py: config parsing/validation/registry, the fullautoand forced-kind resolution matrix, incompatible-combination errors, options forwarding, instance passthrough, kind introspection, server construction from strings, collector-level resolution, and an end-to-end collection run over a forced"queue"transport.DistributedTransportis covered in-process, across spawned processes, and from a real Ray task (verified locally with Ray: the pickled client rendezvouses via the TCPStore and moves payloads over gloo p2p while the driver-side server resolves), plus out-of-order futures, exception propagation, nested keys, timeout semantics, and spec validation.Deferred (tracked follow-ups from the same design note)
DistributedTransport(needs a multi-process single-GPU runner); the gloo path and NCCL spec validation are covered.placement=ray, transport=distributed(nccl)spelling forRayWeightSyncScheme).🤖 Generated with Claude Code