![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 proporciona tres niveles de desarrollo:
1. Componentes (VCL y FMX)
2. Bibliotecas comunes (RTL).
3. Plataformas API (iOS, Android, Mac OS)
En esta publicación discutiremos las Bibliotecas Comunes (RTL).
C ++ Builder tiene varios cientos de funciones, macros y clases a las que puede llamar desde sus programas C y C ++ para realizar una amplia variedad de tareas, incluidas E / S de bajo y alto nivel, manipulación de cadenas y archivos, asignación de memoria, control de procesos , conversión de datos, cálculos matemáticos y más.
La biblioteca de tiempo de ejecución de C ++ Builder (o RTL) se compone de una serie de archivos de encabezado base que proporcionan el soporte subyacente para la mayoría de las bibliotecas de componentes de VCL y FireMonkey. La RTL incluye rutinas globales, clases de utilidad, tales como las que representan las corrientes y las listas, y las clases como TObject, TPersistent y TComponent.
Aunque estrechamente relacionado con FireMonkey y VCL, la RTL no incluye ninguno de los componentes que aparecen en la Paleta de herramientas.
En cambio, las clases y rutinas en la RTL son utilizados por los componentes que no se veía en la paleta de herramientas, y están disponibles para su uso en el código de la aplicación, ya sea en proyectos VCL o proyectos FireMonkey, o cuando se está escribiendo sus propias clases.
Por ejemplo, la cabecera del sistema contiene la mayor parte de la biblioteca de tiempo de ejecución (RTL).
Y desde la cabecera del sistema, usted tiene la System.Math.hpp cabecera que define los clases, rutinas, tipos, variables y constantes relacionadas con las operaciones matemáticas, vectores y matrices.
O el System.Bluetooth.hpp cabecera que ofrece clases para su uso las capacidades Bluetooth del dispositivo que ejecuta la aplicación para conectarse a las aplicaciones que se ejecutan en dispositivos remotos.
O el System.Sensors.hpp cabecera que ofrece clases y componentes que le permiten obtener información y gestionar los sensores del sistema. Los sensores son piezas de hardware o software que pueden proporcionar medidas de las magnitudes físicas a sus aplicaciones.
O el System.Threading.hppencabezado que define los tipos y clases que implementan la biblioteca de programación paralela.
a ver ahora un ejemplo C ++ Builder usando Let cabecera System.Threading.hpp y la Programación Paralela Biblioteca.
Por mi ejemplo de aplicación, voy a estar utilizando un constructor de C ++ 10.4 aplicación de proyecto que utiliza una biblioteca de tiempo de ejecución común, en una aplicación multidispositivo, utilizando el encabezado System.Threading de RTL y la biblioteca de programación paralela.
Puede descargar este ejemplo de aplicación de proyecto TParallelPrime.cbproj aquí.
![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)
Aquí hay una aplicación de proyecto de C ++ Builder que usa una biblioteca de tiempo de ejecución común, en una aplicación multidispositivo, usando el encabezado System.Threading de RTL y la biblioteca de programación paralela.
1 2 3 |
#include <System.Threading.hpp> // TParallel::For #include <System.Diagnostics.hpp> // System::Diagnostics::TStopwatch #include <System.SyncObjs.hpp> // TInterlocked::Increment |
Este ejemplo muestra cómo utilizar el método TParallel.For de la biblioteca de programación paralela (PPL) . TParallel.For divide un bucle for en piezas que se ejecutan en paralelo y utiliza tareas para ejecutar esas piezas.
Esta aplicación encuentra el número de números primos, entre 1 y un valor MAX, como 5 millones en esta aplicación. La aplicación calculará el tiempo para hacer esto usando (1) el bucle for clásico y nosotros haremos lo mismo usando la versión paralela usando el método TParallel.For.
En la interfaz de usuario de las aplicaciones:
El botón “For Loop” lanzará la versión en serie del cálculo de números primos
.
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)); } |
El botón “Parallel Loop” lanzará la versión paralela del cálculo de números primos:
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)); } |
El cuadro Memo muestra los tiempos de cálculo entre el bucle for clásico para (int I = 1; I <= Max; I ++) y la versión del bucle for paralelo utilizando el método TParallel :: For:
![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)
Como podemos ver en los cálculos, la serie For Loop tardó 814 milisegundos en calcular la cantidad de números primos entre 1 y 5 millones, pero solo tomó 267 milisegundos hacer lo mismo usando el método TParallel :: For. I t está claro que el TParallel :: Para el método es más eficiente, y se ejecuta la aplicación mucho más rápido, ya que hace uso de la CPU de procedimientos disponibles para correr en paralelo. La máquina virtual que utilicé para mi partición de Windows está usando 4 núcleos de procesador, así que vemos al usar el método TParallel :: For, ¡la aplicación se ejecuta básicamente 4 veces más rápido! ¡Cuantos más núcleos tenga, más rápido se ejecutará su aplicación utilizando el método TParallel :: For!
Mirando el código, vemos cómo implementamos esta aplicación.
Si coloca el cursor sobre #include <System.Threading.hpp> | Clic derecho | Abra el archivo en el cursor, abrirá su archivo C: Archivos de programa (x86) Embarcadero Studio 21.0 include windows rtl System.Threading.hpp .
Luego, usando Methods Insight | buscar .
![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)
Vemos que tenemos 43 métodos para usar TParallel.For .
Mirando el primero, vemos en este encabezado System.Threading.TParallel.For, ¡incluye una serie de argumentos sobrecargados para que sea muy adecuado para el desarrollo de C ++!
La biblioteca de programación paralela (PPL) incluye esta función de bucle, TParallel :: For , que permite ejecutar sus bucles en paralelo.
Y para todo esto, existe un Thread Pool que se autoajusta automáticamente (en función de la carga en las CPU) para que no tenga que preocuparse por crear o administrar hilos para este propósito.
Para usar la biblioteca de programación paralela en su aplicación, solo incluye el encabezado System.Threading. Este encabezado tiene varias características que se pueden incluir en proyectos de C ++ Builder nuevos y existentes.
Volviendo a la interfaz de usuario de la aplicación, cuando hacemos clic en el botón For Loop, vemos que estamos usando la función For Loop de serie regular, y comprobamos si nuestro número de 1 a 5 millones es un número Prime.
Para verificar si el número es un número primo, usamos esta función en nuestra aplicación
:
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; } } |
A continuación, cuando hacemos clic en el botón Parallel Loop, vemos que estamos usando el método TParallel :: For de RTL. Y en C ++, nuestra función IsPrime debe pasarse al método TParallel.For como un evento iterador o como un Lambda de C ++ 11.
Para el evento Iterator , así es como implementamos la función IsPrime como un evento iterador
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 segunda opción, para que nuestra función C ++ IsPrime se pase al método TParallel.For , es usar una Lambda C ++ 11 para Parallel :: For , como vemos aquí en el código. Aquí vemos nuestra expresión Lambda: [&] (int AIndex) . Esto captura nuestra variable por 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);};})); |
Al ejecutar la aplicación, vimos cómo el TParallel :: For es más eficiente ya que hace uso de las CPU disponibles para ejecutar procedimientos en paralelo. ¡Y esta aplicación también muestra compatibilidad con C ++ 11 en C ++ Builder, incluida la compatibilidad con Lambda Expressions!
En conclusión, C ++ Builder RTL incluye una biblioteca de programación paralela (PPL).
Un gran uso del PPL es hacer que los bucles sean más rápidos utilizando el método TParallel.For.
El PPL, parte de C ++ Builder RTL, en el encabezado System.Threading también brinda a sus aplicaciones la capacidad de ejecutar tareas en paralelo aprovechando el trabajo en múltiples dispositivos de CPU y computadoras. El PPL incluye una serie de funciones avanzadas para ejecutar tareas, unir tareas, esperar grupos de tareas, así como el método TParallel :: For que acabamos de ver en esta aplicación.
Algunas referencias útiles adicionales:
Uso de RTL (biblioteca en tiempo de ejecución )
Tutorial: uso del bucle for de la biblioteca de programación paralela
Video: Cómo utilizar Parallel Prime para C ++ Builder VCL.
Descargue hoy mismo su versión de prueba gratuita de 30 días de C ++ Builder desde este enlace
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition