Files
2026-07-13 13:17:40 +08:00

99 lines
2.7 KiB
Python

import sys
import pytest
import torch
import ray
from ray.util.client.ray_client_helpers import ray_start_client_server
pytest.importorskip("horovod")
try:
from horovod.common.util import gloo_built
from horovod.ray.runner import RayExecutor
except ImportError:
pass # This shouldn't be reached - the test should be skipped.
# For each test, run it once with ray.init() and again with ray client.
@pytest.fixture(params=[False, True])
def ray_start_4_cpus(request):
if request.param:
assert not ray.util.client.ray.is_connected()
with ray_start_client_server(ray_init_kwargs={"num_cpus": 3}):
assert ray.util.client.ray.is_connected()
yield
else:
ray.init(num_cpus=4)
yield
ray.shutdown()
def _train(batch_size=32, batch_per_iter=10):
import timeit
import horovod.torch as hvd
import torch.nn.functional as F
import torch.optim as optim
import torch.utils.data.distributed
hvd.init()
# Set up fixed fake data
data = torch.randn(batch_size, 2)
target = torch.LongTensor(batch_size).random_() % 2
model = torch.nn.Sequential(torch.nn.Linear(2, 2))
optimizer = optim.SGD(model.parameters(), lr=0.01)
# Horovod: wrap optimizer with DistributedOptimizer.
optimizer = hvd.DistributedOptimizer(
optimizer, named_parameters=model.named_parameters()
)
# Horovod: broadcast parameters & optimizer state.
hvd.broadcast_parameters(model.state_dict(), root_rank=0)
hvd.broadcast_optimizer_state(optimizer, root_rank=0)
def benchmark_step():
optimizer.zero_grad()
output = model(data)
loss = F.cross_entropy(output, target)
loss.backward()
optimizer.step()
timeit.timeit(benchmark_step, number=batch_per_iter)
return hvd.local_rank()
@pytest.mark.skipif(not gloo_built(), reason="Gloo is required for Ray integration")
def test_train(ray_start_4_cpus):
def simple_fn(worker):
local_rank = _train()
return local_rank
setting = RayExecutor.create_settings(timeout_s=30)
hjob = RayExecutor(setting, num_workers=3, use_gpu=torch.cuda.is_available())
hjob.start()
result = hjob.execute(simple_fn)
assert set(result) == {0, 1, 2}
result = ray.get(hjob.run_remote(simple_fn, args=[None]))
assert set(result) == {0, 1, 2}
hjob.shutdown()
@pytest.mark.skipif(not gloo_built(), reason="Gloo is required for Ray integration")
def test_horovod_example(ray_start_4_cpus):
from ray.tests.horovod.horovod_example import main
kwargs = {
"data_dir": "./data",
"num_epochs": 1,
}
main(num_workers=1, use_gpu=False, kwargs=kwargs)
if __name__ == "__main__":
sys.exit(pytest.main(["-v", __file__] + sys.argv[1:]))