1 Punkte von GN⁺ 2023-10-08 | 1 Kommentare | Auf WhatsApp teilen
  • Dieser Artikel diskutiert in der Rust-Community die Kontroverse über den Einsatz von Multithread-Executors, also Async-Runtimes, die Work-Stealing einsetzen, um Aufgaben ausgewogen zu verteilen.
  • Einige Rust-Nutzer plädieren für eine alternative Architektur namens "thread-per-core", die bessere Performance verspricht und einfacher zu implementieren sein soll.
  • Der Begriff "thread-per-core" ist irreführend. Jeder Multithread-Executor ist thread-per-core, erzeugt also jeweils einen OS-Thread pro Core und plant darauf Aufgaben ein.
  • Thread-per-core kombiniert drei Ideen: die Behandlung von Parallelität im User Space, asynchrones I/O zur Vermeidung blockierender Threads und die Partitionierung von Daten über CPU-Cores hinweg, um Synchronisierungskosten und Datenbewegungen zwischen CPU-Caches zu eliminieren.
  • Die Kontroverse dreht sich vor allem um den dritten Punkt; mit Async Rust lassen sich die ersten beiden Anforderungen erfüllen.
  • In einer Thread-per-Core-Architektur lassen sich zwei Optimierungen vornehmen: Arbeit zwischen Threads stehlen und möglichst wenig Zustand gemeinsam nutzen.
  • Work-Stealing verbessert die Tail Latency, indem sichergestellt wird, dass alle Threads immer Arbeit haben, ist aber schwer zu implementieren und kann Synchronisierungskosten sowie Cache Misses verursachen.
  • Share-Nothing verbessert die Tail Latency, indem Daten in den schnelleren Caches eines einzelnen CPU-Cores gehalten werden, kann aber bei komplexen Anwendungen, die Zustand über mehrere Partitionen hinweg ändern müssen, schwer umzusetzen sein.
  • Der Artikel schlägt vor, dass Work-Stealing in Systemen mit gemeinsam genutztem Zustand die CPU-Auslastung unter Last verbessern könnte.

1 Kommentare

 
GN⁺ 2023-10-08
Hacker-News-Kommentare
  • Im Kern der Debatte geht es nicht um Thread-per-Core-Work-Stealing-Executors, sondern darum, ob async/await in Rust eine gute Abstraktion ist.
  • Thread-per-Core wurde erfunden, um die Skalierbarkeit und Effizienz von Berechnungen auf typischen Servern mit vielen Kernen zu lösen, und hat sich als hervorragend für I/O-gebundene Workloads mit hohem Durchsatz erwiesen.
  • Die Thread-per-Core-Architektur wird wegen ihrer Skalierbarkeit und Effizienz bleiben, aber die meisten Softwareingenieure haben nur eine begrenzte Intuition dafür, wie ein modernes und idiomatisches Thread-per-Core-Design aussieht.
  • Manche Anwendungen passen besser zu Single-Thread-Systemen, und Rust erlaubt diese Flexibilität.
  • Es gibt Kritik an asynchroner Programmierung in Rust, darunter die Anforderung von Send + Sync + 'static, die einige als belastend empfinden.
  • Die Send-Bound ist eine Anforderung, die das Verschieben von Aufgaben zwischen Executor-Threads erlaubt, und wirkt wie ein Mangel des Async-Systems von Rust.
  • Es gibt keinen pauschalen Ansatz, der für alle Programme die beste Performance erreicht, und die Verwendung von async gilt für viele Rust-Programme als verfrühte Optimierung.
  • Kernel-Kontextwechsel sind teuer, weshalb Thread-per-Core-Designs bevorzugt werden, aber auch Scheduling mit Kontextwechseln im User Space kann problematisch sein.
  • Work Stealing ist eine Methode, um Tail-Latenz zu lösen, bringt aber Cache-Misses und zusätzliche Einschränkungen für Entwickler wie Send, Sync und 'static mit sich.