In den letzten Jahren ist Multi-Core mit mehreren Kernen auf einer CPU üblich geworden. Mit der aktuellen Programmiersprache ist es für Ingenieure jedoch schwierig, Multi-Core-Programme zu erstellen, ohne sich dessen bewusst zu sein. Daher werde ich erklären, wie man Multi-Core aus verschiedenen Sprachen verwendet.
Ein Prozess ist ein laufendes Programm wie eine Anwendung, und ein Thread ist eine Einheit der CPU-Auslastung. Ein Prozess hat einen oder mehrere Threads (siehe unten) und kann so viele Threads verarbeiten, wie CPU-Kerne vorhanden sind. (In den letzten Jahren [SMT](https://ja.wikipedia.org/wiki/%E5%90%8C%E6%99%82%E3%83%9E%E3%83%AB%E3%83% 81% E3% 82% B9% E3% 83% AC% E3% 83% 83% E3% 83% 87% E3% 82% A3% E3% 83% B3% E3% 82% B0) Der Kern kann mehrere Threads verarbeiten, z. B. 2 Threads. Dies entspricht 2 Kernen und 4 Threads.) Um Multi-Core effektiv zu nutzen und ein Programm auszuführen, ist es notwendig, auf der Programmseite eine geeignete Anzahl von Threads für die Anzahl von Kernen zu generieren, die von der CPU verarbeitet werden können. Es ist möglich, mehr Threads als die Anzahl der Kerne zu erstellen, aber die CPU kann nur so viele Threads verarbeiten, wie Kerne vorhanden sind, und es besteht das Problem, dass die Verarbeitung aufgrund des Wechsels der auszuführenden Threads verlangsamt wird.
Es gibt ähnliche Begriffe, parallel und gleichzeitig, aber sie sind unterschiedlich. Parallel ist ein Fall, in dem mehrere Prozesse gleichzeitig verarbeitet werden und mehrere Threads von mehreren Kernen verarbeitet werden. (Es können nicht mehrere Prozesse gleichzeitig mit einem einzigen Kern ausgeführt werden, sodass keine Parallelität erzielt werden kann.) Gleichzeitig bedeutet, dass mehrere Prozesse gleichzeitig geschaltet und ausgeführt werden, sodass ein Thread mehrere Prozesse wechseln und ausführen kann. Da es möglich ist, während des Umschaltens der Verarbeitung in mehreren Threads ausgeführt zu werden, ist es auch möglich, parallel und parallel zu realisieren.
Apache, ein Webserver, verwendet eine Methode, um einen Prozess für jede Benutzeranforderung zu generieren. Wenn die Anzahl der Clients etwa 10.000 erreicht, sinkt die Antwortleistung erheblich, obwohl die Hardwareleistung des Webservers einen Spielraum aufweist. Es gab ein C10K-Problem. (Die spezifische Ursache des C10K-Problems war in diesem Artikel leicht zu verstehen.) Daher haben wir in nginx und Node.js versucht, das C10K-Problem zu lösen, indem wir parallel verarbeitet haben, indem wir asynchrone E / A mit einem einzelnen Thread verarbeitet haben.
Node.js Wie oben erwähnt, arbeitet Node.js in einem einzelnen Thread, und der Ansatz besteht darin, die Verarbeitung parallel zur asynchronen Verarbeitung wie async / await durchzuführen. Wie in der folgenden Abbildung gezeigt, ist das Bild so, dass beim Zugriff auf eine externe API eine andere Verarbeitung durchgeführt wird, bis das Ergebnis zurückgegeben wird, und wenn das Ergebnis erhalten wird, wird die Verarbeitung fortgesetzt. (Für Details war dieser Artikel leicht zu verstehen.) Daher ist es bei der Durchführung einer asynchronen Standardverarbeitung nicht möglich, die Leistung von Multi-Core zu verbessern. Daher verwendet Node.js Cluster, um mehrere Prozesse zu erstellen (https://postd.cc/setting-up-a-node-js). Sie müssen entweder -cluster /) oder mehrere Threads mit worker_threads erstellen. Um den Multi-Core-Kern auf diese Weise nutzen zu können, müssen mehrere Prozesse oder Threads programmseitig erstellt werden. In Multi-Threads können Sie den Wert von Variablen gemeinsam nutzen. In Multi-Prozessen wird der Speicherplatz jedoch getrennt. [Vor- und Nachteile], den Wert von Variablen nicht teilen zu können (https://stackoverflow.com/questions/56656498/how-is-cluster-and-worker-threads-work-in-node-js) Existiert.
In Node.js konnte ich Multi-Core nutzen, indem ich mehrere Prozesse oder Threads erstellte. In Ruby und Python jedoch [Global Interpolator Lock (GIL)](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AD%E3%83%BC%E3%83% 90% E3% 83% AB% E3% 82% A4% E3% 83% B3% E3% 82% BF% E3% 83% 97% E3% 83% AA% E3% 82% BF% E3% 83% AD% Es gibt so etwas wie E3% 83% 83% E3% 82% AF), und selbst wenn Sie mehrere Threads erstellen, können diese nicht parallel ausgeführt werden. (Um genau zu sein, ist es der Fall, dass CPython und CRuby in C-Sprache implementiert sind, aber hier wird es weggelassen.) Wenn Sie versuchen, Multi-Core in diesen Sprachen zu nutzen, kann dies nicht durch Multithreading realisiert werden, und Sie müssen mehrere Prozesse erstellen.
In der Go-Sprache wird die asynchrone Verarbeitung parallel und parallel unter Verwendung einer sogenannten Goroutine realisiert, und standardmäßig wird die Anzahl der CPU-Kerne als "GOMAX PROCS" festgelegt. Es werden so viele Threads wie dieser Wert vorbereitet, und die Goroutine für leichte Threads wird in den Threads ausgeführt. Die folgende Abbildung zeigt ein Bild, wenn die Anzahl der CPU-Kerne 4 und "GOMAX PROCS = 4" beträgt. Wenn Sie Goroutine auf diese Weise verwenden, können Sie Programme parallel und parallel ausführen, indem Sie die Vorteile von Multi-Core nutzen. (Aus dem Grund, warum Goroutine leicht ist, war dieser Artikel leicht zu verstehen.)
In Rust kann die asynchrone Verarbeitung mit async / await ausgeführt werden. Zu diesem Zeitpunkt können Sie die Ausführungszuweisungsmethode für asynchrone Verarbeitungsthreads auswählen, je nachdem, welche Laufzeit verwendet wird. Eine beliebte Laufzeit ist tokio. In Tokio werden Threads für die Anzahl der Kerne erstellt, und die asynchrone Verarbeitung wird an diese Threads übergeben, ähnlich wie bei Goroutine die Verwendung von Multi-Core. (Für andere Zuweisungsmethoden und asynchrone Verarbeitung in Rust war dieser Artikel leicht zu verstehen. Insbesondere [Über das Ausführungsmodell hier](https://tech-blog.optim.co.jp/entry/2019/11/08/163000#%E5%AE%9F%E8%A1%8C%E3%83% A2% E3% 83% 87% E3% 83% AB) ist leicht zu verstehen.)
In Ruby und Python ist es aufgrund des Mechanismus schwierig, Multithreading zu erstellen, und bei der asynchronen Verarbeitung von Node.js konnte Multi-Core nicht verwendet werden. In der Go-Sprache und Rust, die in den letzten Jahren populär waren, kann durch Aufrufen der asynchronen Verarbeitung eine parallele und parallele Verarbeitung durchgeführt werden, ohne dass der Ingenieur davon Kenntnis hat, und es kann Multi-Core verwendet werden. Es ist verständlich, dass die Go-Sprache und Rust in der heutigen Zeit beliebt sind, in der Multi-Core-CPUs alltäglich geworden sind.
[Abbildung] Unterschiede zwischen CPU-Kernen, Threads und Prozessen, Kontextwechseln und Multithreading Annäherung an das asynchrone Verständnis von Unity durch Kenntnis des Unterschieds zwischen Prozessen, Threads und Aufgaben Ich habe die asynchrone E / A von Node.js untersucht Node.js kann ich nicht mehr hören Ich habe GIL untersucht, das Sie wissen sollten, wenn Sie parallel mit Python arbeiten Warum Goroutine leicht ist [Master Rust Asynchronous Programming](https://tech-blog.optim.co.jp/entry/2019/11/08/163000#%E3%83%A9%E3%83%B3%E3%82 % BF% E3% 82% A4% E3% 83% A0% E3% 81% A7% E9% 9D% 9E% E5% 90% 8C% E6% 9C% 9F% E3% 82% BF% E3% 82% B9 % E3% 82% AF% E3% 82% 92% E8% B5% B7% E5% 8B% 95% E3% 81% 99% E3% 82% 8B)
Recommended Posts