conc_workload.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. """Aggregate decode tok/s with N concurrent streams of one workload, each stream a
  2. different prompt (identical prompts would route to the same experts).
  3. python3 conc_workload.py WORKLOAD N [N ...] WORKLOAD: code | prose | structured | mixed
  4. """
  5. import json, os, re, statistics, sys, threading, time, urllib.request
  6. from prompts import prompt_for
  7. BASE = os.environ.get("GATE_URL", "http://127.0.0.1:8002")
  8. MODEL = os.environ.get("GATE_MODEL", "glm53")
  9. def metrics():
  10. raw = urllib.request.urlopen(BASE + "/metrics", timeout=30).read().decode()
  11. get = lambda k: sum(float(v) for v in re.findall(rf"^vllm:{k}\S*\s+([0-9.e+]+)$", raw, re.M))
  12. return get("spec_decode_num_accepted_tokens_total"), get("spec_decode_num_drafts_total")
  13. def one(prompt, out, i):
  14. body = json.dumps({"model": MODEL, "max_tokens": 512, "temperature": 0, "stream": True,
  15. "chat_template_kwargs": {"thinking": False, "enable_thinking": False},
  16. "stream_options": {"include_usage": True},
  17. "messages": [{"role": "user", "content": prompt}]}).encode()
  18. r = urllib.request.urlopen(urllib.request.Request(BASE + "/v1/chat/completions", data=body,
  19. headers={"Content-Type": "application/json"}), timeout=900)
  20. first = n = None
  21. for line in r:
  22. if not line.startswith(b"data: {"):
  23. continue
  24. d = json.loads(line[6:])
  25. if first is None and d.get("choices"):
  26. first = time.monotonic()
  27. if d.get("usage"):
  28. n = d["usage"]["completion_tokens"]
  29. out[i] = (n, first, time.monotonic())
  30. work = sys.argv[1]
  31. for N in [int(a) for a in sys.argv[2:]]:
  32. prompts = [prompt_for(work, i) for i in range(N)]
  33. a0, d0 = metrics()
  34. out = [None] * N
  35. ts = [threading.Thread(target=one, args=(prompts[i], out, i)) for i in range(N)]
  36. for t in ts: t.start()
  37. for t in ts: t.join()
  38. a1, d1 = metrics()
  39. t0 = min(o[1] for o in out); t1 = max(o[2] for o in out)
  40. per = [o[0] / (o[2] - o[1]) for o in out]
  41. al = 1 + (a1 - a0) / max(d1 - d0, 1) # tokens per verify step per request
  42. print(f"{work:<10} streams {N:2d}: aggregate {sum(o[0] for o in out) / (t1 - t0):6.1f} tok/s,"
  43. f" per stream median {statistics.median(per):5.1f}, accepted per step {al:.2f}", flush=True)