Quazim0t0's picture
Old-hardware training through emulated GPU logic
309b968 verified
Raw
History Blame Contribute Delete
3.29 kB
"""P2P cluster scanner: probe each node's agent, measure latency, gather
resources + live status, compute the capacity plan and readiness verdict."""
import json
import socket
import time
import urllib.request
def _get(url, timeout=2.0):
with urllib.request.urlopen(url, timeout=timeout) as r:
return json.load(r)
def _latency_ms(host, port, timeout=2.0):
t = time.time()
try:
with socket.create_connection((host, int(port)), timeout=timeout):
return (time.time() - t) * 1000.0
except Exception:
return None
def scan_node(node):
host, ap = node["host"], node.get("agent_port", 8900)
base = f"http://{host}:{ap}"
out = {"name": node["name"], "host": host, "reachable": False,
"latency_ms": None, "resources": None, "status": None,
"gloo_port_open": None}
lat = _latency_ms(host, ap)
out["latency_ms"] = round(lat, 1) if lat is not None else None
if lat is None:
return out
try:
h = _get(f"{base}/health")
out["reachable"] = bool(h.get("ok"))
out["rank"] = h.get("rank")
out["resources"] = _get(f"{base}/resources")
out["status"] = _get(f"{base}/status")
except Exception as e:
out["error"] = str(e)
gp = node.get("gloo_port")
if gp:
out["gloo_port_open"] = _latency_ms(host, gp) is not None
return out
def capacity_plan(scans, base_batch=32):
live = [n for n in scans if n.get("resources")]
caps = [float(n["resources"].get("capacity") or n["resources"].get("cores", 1))
for n in live]
total = sum(caps) or 1
world = len(live)
gb = base_batch * max(1, world)
batches = [max(1, round(gb * c / total)) for c in caps]
tb = sum(batches) or 1
weights = [b / tb for b in batches]
rams = [n["resources"].get("ram_gb") for n in live
if n["resources"].get("ram_gb") is not None]
return {"world": world, "total_cores": sum(n["resources"].get("cores", 0) for n in live),
"total_ram_gb": round(sum(rams), 1) if rams else None,
"per_node": [{"name": n["name"], "device": n["resources"].get("device", "cpu"),
"cores": n["resources"].get("cores"),
"gpu": (n["resources"].get("gpu") or {}).get("name"),
"capacity": round(c, 1), "weight": round(w, 3), "batch": b,
"ram_gb": n["resources"].get("ram_gb")}
for n, c, w, b in zip(live, caps, weights, batches)],
"global_batch": sum(batches)}
def scan_cluster(nodes, expected_world=None, base_batch=32):
scans = [scan_node(n) for n in nodes]
plan = capacity_plan(scans, base_batch)
reachable = [s for s in scans if s["reachable"]]
want = expected_world if expected_world is not None else len(nodes)
ready = (len(reachable) == len(nodes) == want)
train = None
for s in scans:
st = s.get("status") or {}
if st.get("rank") == 0 and st:
train = st
break
return {"nodes": scans, "plan": plan, "ready": ready,
"reachable": len(reachable), "total": len(nodes),
"expected_world": want, "training": train,
"scanned_at": time.strftime("%H:%M:%S")}