![Barcode For FMX | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/Barcode-For-FMX-1.jpg?resize=1024%2C694&ssl=1)
C++Builder bietet drei Entwicklungsstufen:
1. Komponenten (VCL und FMX)
2. Allgemeine Bibliotheken (RTL).
3. Plattform-APIs (iOS, Android, Mac OS)
In diesem Beitrag werden die Common Libraries (RTL) erläutert.
C++Builder verfügt über mehrere hundert Funktionen, Makros und Klassen, die Sie in Ihren C- und C++ – Programmen aufrufen, um eine Vielzahl von Aufgaben auszuführen, darunter E / A auf niedriger und hoher Ebene, Manipulation von Zeichenfolgen und Dateien, Speicherzuweisung und Prozesssteuerung , Datenkonvertierung, mathematische Berechnungen und mehr.
Die C++Builder-Laufzeitbibliothek (RTL) besteht aus einer Reihe von Basis-Header-Dateien, die die zugrunde liegende Unterstützung für die meisten VCL- und FireMonkey-Komponentenbibliotheken bieten. Das RTL umfasst globale Routinen, Utility – Klassen wie diejenigen , die Bäche und Listen und Klassen wie TObject, TPersistent und TComponent dar.
Obwohl eng mit Firemonkey und VCL verbündete, hat das RTL gehört keine der Komponenten , die auf dem erscheinen Werkzeugpalette.
Stattdessen werden die Klassen und Routinen in dem RTL durch die Komponenten verwendet , die auf der Tool – Palette erscheinen zu tun, und sind für Sie in Anwendungscode entweder in VCL – Projekten oder Projekten verwenden , um Firemonkey, oder wenn Sie Ihre eigenen Klassen schreiben.
Zum Beispiel enthält das System – Header die meisten der Laufzeitbibliothek (RTL). .
Und aus dem Header – System haben Sie den System.Math.hpp Header , die definiert , Klassen, Routinen, Typen, Variablen und Konstanten zu mathematischen Operationen, Vektoren und Matrizen zusammen.
Oder die System.Bluetooth.hpp Header , die Klassen zu verwenden liefert die Bluetooth – Funktionen des Geräts , das die Anwendung ausgeführt wird, um Anwendungen zu verbinden , die auf entfernten Geräten ausgeführt werden .
Oder der System.Sensors.hpp Header, Klassen und Komponenten , mit denen Sie Informationen lassen erhalten und Systemsensoren verwalten. Die Sensoren sind Teile der Hardware oder Software , die Maßnahmen von physikalischen Größen , um Ihre Anwendungen zur Verfügung stellen kann.
Oder die System.Threading.hppHeader , die definiert , Klassen und Typen, die die Umsetzung der parallelen Programmierung Bibliothek.
Es sei nun an einem Beispiel C++Builder sehen die Verwendung System.Threading.hpp Header und die Parallele Programmierung Bibliothek.
Für meine Beispielanwendung, werde ich eine C++Builder 10.4 verwenden Projektanwendung, die eine Common Run Time Library in einer Multi-Device-Anwendung unter Verwendung des System.Threading-Headers der RTL und der Parallel Programming Library verwendet.
Sie können diese Beispielprojektanwendung TParallelPrime.cbproj hier herunterladen .
![UI | Embarcadero RAD Studio Delphi C++Builder Blogs ui 4](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/UI.jpg?resize=642%2C234&ssl=1)
Hier ist eine C++Builder-Projektanwendung, die eine allgemeine Laufzeitbibliothek in einer Anwendung mit mehreren Geräten unter Verwendung des System.Threading- Headers der RTL und der Parallel Programming Library verwendet.
1 2 3 |
#include <System.Threading.hpp> // TParallel::For #include <System.Diagnostics.hpp> // System::Diagnostics::TStopwatch #include <System.SyncObjs.hpp> // TInterlocked::Increment |
Dieses Beispiel zeigt, wie die TParallel.For-Methode aus der Parallel Programming Library (PPL) verwendet wird . TParallel.For teilt eine for-Schleife in Teile auf, die parallel ausgeführt werden, und verwendet Aufgaben, um diese Teile auszuführen.
Diese Anwendung ermittelt die Anzahl der Primzahlen zwischen 1 und einem MAX-Wert, wie z. B. 5 Millionen in dieser Anwendung. Die Anwendung berechnet die Zeit dafür mit (1) der klassischen for-Schleife und wir tun dasselbe mit der parallelen Version mit der TParallel.For-Methode.
Auf der Benutzeroberfläche der Anwendungen:
Die Schaltfläche „For Loop“ startet die serielle Version der Primzahlenberechnung.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Button event handler that finds prime numbers using the classic for loop void __fastcall TForm2::btnForLoopClick(TObject *Sender) { int Max = 5000000; // 5 Million Tot = 0; System::Diagnostics::TStopwatch sw = System::Diagnostics::TStopwatch::Create(); sw.Start(); for (int I = 1; I <= Max; I++) { if (IsPrime(I)) { Tot++; } } sw.Stop(); Memo1->Lines->Add (String().sprintf (L"Sequential For loop. Time (in milliseconds): %lld, Primes found: %lld", sw.ElapsedMilliseconds, Tot)); } |
Die Schaltfläche „Parallelschleife“ startet die parallele Version der Primzahlenberechnung:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Button event handler that finds prime numbers using the Parallel::For method void __fastcall TForm2::btnParallelLoopClick(TObject *Sender) { int Max = 5000000; // 5 Million Tot = 0; System::Diagnostics::TStopwatch sw = System::Diagnostics::TStopwatch::Create(); sw.Start(); // In C++, the IsPrime function passes to the TParallel.For as an Iterator Event. TParallel::For(NULL, 1, Max, MyIteratorEvent); // Second option is to use a C++11 Lambda for the Parallel::For /* TParallel::For(NULL, 1, Max, System::Sysutils::_di_TProc__1<int>( // [this] (int AIndex) { [&](int AIndex) { if (IsPrime(AIndex)) {TInterlocked::Increment(Tot);};})); */ sw.Stop(); Memo1->Lines->Add (String().sprintf (L"Parallel For loop. Time (in milliseconds): %lld, Primes found: %lld", sw.ElapsedMilliseconds, Tot)); } |
Das Feld Memo zeigt die Berechnungszeiten zwischen der klassischen for-Schleife für (int I = 1; I <= Max; I ++) und der parallelen for-Schleifenversion mit der TParallel :: For- Methode an
![Memo | Embarcadero RAD Studio Delphi C++Builder Blogs memo 3](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/Memo.jpg?resize=474%2C53&ssl=1)
Wie aus den Berechnungen hervorgeht, dauerte die serielle For-Schleife 814 Millisekunden, um die Anzahl der Primzahlen zwischen 1 und 5 Millionen zu berechnen, aber es dauerte nur 267 Millisekunden, um dasselbe mit der TParallel :: For-Methode zu tun. Es ist nicht klar, dass die TParallel :: For-Methode effizienter ist und die Anwendung viel schneller ausführt, da sie die verfügbaren CPUs zum parallelen Ausführen von Prozeduren verwendet. Die virtuelle Maschine, die ich für meine Windows-Partition verwendet habe, verwendet 4 Prozessorkerne. Bei Verwendung der TParallel :: For-Methode wird die Anwendung also im Grunde viermal schneller ausgeführt! Je mehr Kerne Sie haben, desto schneller wird Ihre Anwendung mit der TParallel :: For-Methode ausgeführt!
Wenn wir uns den Code ansehen, sehen wir, wie wir diese Anwendung implementiert haben.
Wenn Sie mit der Maus über #include <System.Threading.hpp> | fahren Rechtsklick | Öffnen Sie die Datei unter dem Cursor. Sie öffnen Ihre Datei C: Programme (x86) Embarcadero Studio 21.0 include windows rtl System.Threading.hpp .
Verwenden Sie dann Methods Insight | Suche nach .
![For | Embarcadero RAD Studio Delphi C++Builder Blogs for 3](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/For.jpg?resize=556%2C262&ssl=1)
Wir sehen, dass wir 43 Methoden zur Verwendung von TParallel haben .
Wenn wir uns das erste ansehen, sehen wir in diesem System.Threading.TParallel.For-Header, der eine Reihe überladener Argumente enthält , um es für die C ++ – Entwicklung sehr gut geeignet zu machen!
Die Parallel Programming Library (PPL) enthält die Schleifenfunktion TParallel :: For , mit der die Schleifen parallel ausgeführt werden können!
Und für all dies gibt es einen Thread-Pool, der sich automatisch selbst optimiert (basierend auf der Belastung der CPUs), sodass Sie sich nicht um das Erstellen oder Verwalten von Threads für diesen Zweck kümmern müssen!
So verwenden Sie die Bibliothek für parallele Programmierung in Ihrer Anwendung, einschließlich des System.Threading-Headers. Dieser Header verfügt über mehrere Funktionen, die in neue und vorhandene C ++ Builder-Projekte aufgenommen werden können.
Wenn wir in die Benutzeroberfläche der Anwendungen zurückkehren und auf die Schaltfläche For Loop klicken, sehen wir, dass wir die reguläre serielle For Loop-Funktion verwenden, und prüfen, ob unsere Nummer von 1 bis 5 Millionen eine Primzahl ist.
Um zu überprüfen, ob die Zahl eine Primzahl ist, verwenden wir diese Funktion in unserer Anwendung
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
bool __fastcall TForm2::IsPrime(int N) { int Test, k; bool aPrime; if (N <= 3) { return N > 1; } else if (((N % 2) == 0) || ((N % 3) == 0)) { return false; } else { aPrime = true; k = (int)sqrt(N); Test = 5; while (Test <= k) { if (((N % Test) == 0) || ((N % (Test + 2)) == 0)) { aPrime = false; break; // jump out of the for loop } Test = Test + 6; } return aPrime; } } |
Wenn wir als nächstes auf die Schaltfläche Parallel Loop klicken, sehen wir, dass wir die TParallel :: For-Methode der RTL verwenden. In C + muss unsere IsPrime-Funktion als Iterator-Ereignis oder als C++ 11-Lambda an die TParallel.For-Methode übergeben werden.
Für das Iterator-Ereignis haben wir die IsPrime-Funktion wie folgt als Iterator-Ereignis implementiert
1 2 3 4 5 6 7 8 9 10 11 12 |
// Parallel For Iterator Event Proc void __fastcall TForm2::MyIteratorEvent(TObject* Sender, int AIndex) { // The Iterator Event implementation code is as follows. // In C++ you create an Iterator event function or C++11 lambda and // pass that as part of the TParallel::For loop call. // // Within parallel loops, you must transform your operations into thread-safe operations. // Here we use a member of the RTL System.SyncObjs header, the TInterlocked method. if (IsPrime(AIndex)) { TInterlocked::Increment(Tot); } } |
Die zweite Option für die Übergabe unserer C++ IsPrime-Funktion an die TParallel.For-Methode ist die Verwendung eines C++ 11-Lambda für Parallel :: For , wie wir hier im Code sehen. Hier sehen wir unseren Lambda-Ausdruck: [&] (int AIndex) . Dies erfasst unsere Variable durch ref
1 2 3 4 5 |
// Second option is to use a C++11 Lambda for the Parallel::For TParallel::For(NULL, 1, Max, System::Sysutils::_di_TProc__1<int>( // [this] (int AIndex) { [&](int AIndex) { if (IsPrime(AIndex)) {TInterlocked::Increment(Tot);};})); |
Wenn Sie dieselbe Anwendung mit dem Lambda-Code ausführen, erhalten Sie dieselben Ergebnisse.
Beim Ausführen der Anwendung haben wir gesehen, wie effizient TParallel :: For ist, da es die verfügbaren CPUs zum parallelen Ausführen von Prozeduren verwendet. Und diese Anwendung zeigt auch C++ 11-Unterstützung in C++ Builder, einschließlich Unterstützung für Lambda Expressions!
Zusammenfassend enthält die C++Builder RTL eine Parallel Programming Library (PPL).
Eine großartige Verwendung der PPL besteht darin, die Schleife mithilfe der TParallel.For-Methode zu beschleunigen.
Die PPL, Teil von C++Builder RTL, im System.Threading-Header bietet Ihren Anwendungen auch die Möglichkeit, Aufgaben parallel auszuführen und die Arbeit auf mehreren CPU-Geräten und Computern zu nutzen. Die PPL enthält eine Reihe erweiterter Funktionen zum Ausführen von Aufgaben, Verbinden von Aufgaben, Warten auf Gruppen von Aufgaben sowie die TParallel :: For-Methode, die wir gerade in dieser Anwendung gesehen haben.
Einige zusätzliche nützliche Referenzen:
Verwenden der RTL (Run-Time Library )
Tutorial: Verwenden der For-Schleife aus der Bibliothek für parallele Programmierung
Video: Verwendung der VCL von Parallel Prime für C++Builder.
Laden Sie noch heute Ihre kostenlose 30-Tage-Testversion von C++Builder von diesem Link herunter
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition