C ++ Builder propose trois niveaux de développement:
1. Composants (VCL et FMX)
2. Bibliothèques communes (RTL).
3. API de plate-forme (iOS, Android, Mac OS)
Dans cet article, nous discuterons des bibliothèques communes (RTL).
C ++ Builder a plusieurs centaines de fonctions, macros et classes que vous appelez à partir de vos programmes C et C ++ pour effectuer une grande variété de tâches, y compris les E / S de bas et haut niveau, la manipulation de chaînes et de fichiers, l’allocation de mémoire, le contrôle de processus , conversion de données, calculs mathématiques, etc.
La bibliothèque d’exécution C ++ Builder (ou RTL) est composée d’un certain nombre de fichiers d’en-tête de base qui fournissent la prise en charge sous-jacente de la plupart des bibliothèques de composants VCL et FireMonkey. Le RTL inclut des routines globales, des classes de services publics tels que ceux qui représentent des flux et des listes et des classes telles que TObject, TPersistent et TComponent.
Même si étroitement lié avec FireMonkey et VCL, RTL ne comprend aucun des éléments qui apparaissent sur la Palette d’outils.
Au lieu de cela, les classes et les routines du RTL sont utilisées par les composants qui apparaissent sur la palette d’ outils, et sont disponibles pour vous d’utiliser dans le code d’application soit dans des projets de VCL ou des projets FireMonkey, ou lorsque vous écrivez vos propres classes.
Par exemple, l’ en- tête du système contient plus de la bibliothèque d’ exécution (RTL).
Et à partir de l’ en- tête système, vous avez la System.Math.hpp tête qui définit les classes, les routines, les types, les variables et les constantes liées aux opérations mathématiques, des vecteurs et des matrices.
Ou la System.Bluetooth.hpp – tête qui fournit des classes à l’ utilisation les capacités Bluetooth du dispositif qui exécute votre application pour se connecter à des applications fonctionnant sur des périphériques distants.
Ou l’ System.Sensors.hpp – tête qui fournit des classes et des composants qui vous permettent d’ obtenir des informations et de gérer des capteurs du système. Les capteurs sont des pièces de matériel ou de logiciels qui peuvent fournir des mesures de grandeurs physiques à vos applications.
Ou le System.Threading.hppen- tête qui définit les classes et types qui mettent en œuvre la bibliothèque de programmation parallèle.
Regardons maintenant un exemple C ++ Builder en utilisant la tête System.Threading.hpp et la bibliothèque de programmation parallèle.
Pour mon application exemple, je vais utiliser un C ++ Builder 10.4 application de projet qui utilise une bibliothèque d’exécution commune, dans une application multi-périphérique, en utilisant l’en-tête System.Threading du RTL et la bibliothèque de programmation parallèle.
Vous pouvez télécharger cet exemple d’application de projet TParallelPrime.cbproj ici.
Voici une application de projet C ++ Builder qui utilise une bibliothèque d’exécution commune, dans une application multi-périphérique, en utilisant l’en- tête System.Threading du RTL et la bibliothèque de programmation parallèle.
1 2 3 |
#include <System.Threading.hpp> // TParallel::For #include <System.Diagnostics.hpp> // System::Diagnostics::TStopwatch #include <System.SyncObjs.hpp> // TInterlocked::Increment |
Cet exemple montre comment utiliser la méthode TParallel.For de la bibliothèque de programmation parallèle (PPL) . TParallel.For divise une boucle for en morceaux qui s’exécutent en parallèle et utilise des tâches pour exécuter ces morceaux.
Cette application trouve le nombre de nombres premiers, entre 1 et une valeur MAX, comme 5 millions dans cette application. L’application calculera le temps pour le faire en utilisant (1) la boucle for classique et nous ferons de même en utilisant la version parallèle en utilisant la méthode TParallel.For.
Sur l’interface utilisateur des applications:
Le bouton «For Loop» lancera la version série du calcul des nombres premier
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)); } |
Le bouton «Parallel Loop» lancera la version parallèle du calcul des nombres premiers:
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)); } |
La boîte Memo affiche les temps de calcul entre la boucle for classique pour (int I = 1; I <= Max; I ++) et la version parallèle pour la boucle en utilisant la méthode TParallel :: For:
Comme nous pouvons le voir à partir des calculs, il a fallu 814 millisecondes à la série For Loop pour calculer le nombre de nombres premiers entre 1 et 5 millions, mais cela n’a pris que 267 millisecondes pour faire de même en utilisant la méthode TParallel :: For. Il est clair que la méthode TParallel :: For est plus efficace et exécute l’application beaucoup plus rapidement, car elle utilise les processeurs disponibles pour exécuter des procédures en parallèle. La machine virtuelle que j’ai utilisée pour ma partition Windows utilise 4 cœurs de processeur, donc nous voyons qu’en utilisant la méthode TParallel :: For, l’application fonctionne fondamentalement 4 fois plus vite! Plus vous avez de cœurs, plus votre application s’exécutera rapidement en utilisant la méthode TParallel :: For!
En regardant le code, nous voyons comment nous avons implémenté cette application.
Si vous placez le curseur sur le #include <System.Threading.hpp> | Clic droit | Ouvrez le fichier au curseur, vous ouvrirez votre fichier C: Program Files (x86) Embarcadero Studio 21.0 include windows rtl System.Threading.hpp .
Puis en utilisant Methods Insight | recherchez For
Nous voyons que nous avons 43 méthodes pour utiliser TParallel.For .
En regardant le premier, nous voyons dans cet en-tête System.Threading.TParallel.For, il comprend un certain nombre d’ arguments surchargés pour le rendre très approprié pour le développement C ++!
La bibliothèque de programmation parallèle (PPL) comprend cette fonction de boucle, TParallel :: For , qui permet d’exécuter ses boucles en parallèle!
Et pour tout cela, il y a un Thread Pool qui s’auto-règle automatiquement (en fonction de la charge sur le CPU) afin que vous n’ayez pas à vous soucier de créer ou de gérer des threads à cet effet!
Pour utiliser la bibliothèque de programmation parallèle dans votre application, en incluant uniquement l’en- tête System.Threading. Cet en-tête a plusieurs fonctionnalités qui peuvent être incluses dans des projets C ++ Builder nouveaux et existants.
En revenant dans l’interface utilisateur des applications, lorsque nous cliquons sur le bouton For Loop, nous voyons que nous utilisons la fonction série régulière For Loop, et nous vérifions si notre nombre de 1 à 5 millions est un nombre premier.
Pour vérifier si le nombre est un nombre premier, nous utilisons cette fonction dans notre application
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; } } |
Ensuite, lorsque nous cliquons sur le bouton Parallel Loop, nous voyons que nous utilisons la méthode TParallel :: For du RTL. Et en C ++, notre fonction IsPrime doit être transmise à la méthode TParallel.For en tant qu’événement Iterator ou en tant que Lambda C ++ 11.
Pour l’ événement Iterator , voici comment nous avons implémenté la fonction IsPrime en tant qu’événement Iterator
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); } } |
La deuxième option, pour que notre fonction C ++ IsPrime soit transmise à la méthode TParallel.For , consiste à utiliser un Lambda C ++ 11 pour Parallel :: For , comme nous le voyons ici dans le code. Ici, nous voyons notre expression Lambda: [&] (int AIndex) . Cela capture notre variable par réf
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);};})); |
i vous exécutez la même application en utilisant le code Lambda, vous obtiendrez les mêmes résultats.
En exécutant l’application, nous avons vu comment TParallel :: For est plus efficace car il utilise les processeurs disponibles pour exécuter des procédures en parallèle. Et cette application montre également la prise en charge de C ++ 11 dans C ++ Builder, y compris la prise en charge des expressions Lambda!
En conclusion, le C ++ Builder RTL comprend une bibliothèque de programmation parallèle (PPL).
Une grande utilisation de la PPL est de rendre la boucle plus rapide, en utilisant la méthode TParallel.For.
La PPL, qui fait partie de C ++ Builder RTL, dans l’en-tête System.Threading donne également à vos applications la possibilité d’exécuter des tâches en parallèle en tirant parti de l’utilisation de plusieurs processeurs et ordinateurs. La PPL comprend un certain nombre de fonctionnalités avancées pour exécuter des tâches, joindre des tâches, attendre des groupes de tâches, ainsi que la méthode TParallel :: For que nous venons de voir dans cette application.
Quelques références utiles supplémentaires:
Utilisation de la RTL (Run-Time Library )
Tutoriel: Utilisation de la boucle For de la bibliothèque de programmation parallèle
Vidéo: Comment utiliser Parallel Prime pour C ++ Builder VCL.
Téléchargez votre essai gratuit de 30 jours C ++ Builder aujourd’hui à partir de ce lien
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition