Marco Cantu publicó el interesante artículo Explaining Tasks in Delphi Parallel Library… by Creating too Many Tasks en donde usaba TTask con Delphi para procesar datos en paralelo usando diferentes hilos de ejecución.

Entonces decidí profundizar más en TParallel de Embarcadero, el objeto que encapsula las tareas en paralelo dentro de PPL (Parallel Programming Library), y con el que sin duda tendré que trabajar para implementar el soporte multithreading en FileOptimizer.

El concepto es lógico, puesto que la mayor parte de la complejidad es transparente para el programador, y gracias al Using the For Loop from the Parallel Programming Library, se entiende muy bien.

El problema es que el código se expone por partes, como conclusión de las explicaciones, y que éste no llega a compilar debido a que la función sqrt no tiene ninguna sobrecarga que acepte como argumento un entero:

k = (int)sqrt(N);

sqrt acepta float y double, pero no int como es el caso, de manera que me propuse solucionar todas estas carencias.
– Corregir el error de compilación de sqrt.
– Proporcionar el código completo.
– Aumentar las iteraciones totales de 5.000.000 a 50.000.000, para resaltar mejor la diferencia de rendimiento.
– Hacer que el formulario pueda maximizarse, y que todos los controles tengan un nombre más descriptivo.
– Refactorizar y formatear el código para resultar más claro y legible.
– Aplicar alguna optimización menor.



Finalmente el código completo ha quedado así:

cppMain.cpp

// ---------------------------------------------------------------------------
 
#include <vcl.h>
#include <System.Threading.hpp>
#include <System.Diagnostics.hpp>
#include <System.SyncObjs.hpp>
#pragma hdrstop
#include "cppMain.h"
 
 
const unsigned int KI_MAX = 50000000;
 
 
// ---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
 
 
 
// ---------------------------------------------------------------------------
__fastcall TfrmMain::TfrmMain(TComponent* Owner): TForm(Owner)
{
}
 
 
 
// ---------------------------------------------------------------------------
void __fastcall TfrmMain::butForLoopClick(TObject *Sender)
{
	unsigned int iTot = 0;
 
 
	System::Diagnostics::TStopwatch sw = System::Diagnostics::TStopwatch::Create();
	sw.Start();
 
	for (unsigned int iCont = 1; iCont <= KI_MAX; iCont++)
	{
		if (IsPrime(iCont))
		{
			iTot++;
		}
	}
 
	sw.Stop();
	mmoResults->Lines->Add(String().sprintf(L"Sequential For loop. Time (in milliseconds): %lld, Primes found: %u", sw.ElapsedMilliseconds, iTot));
}
 
 
 
 
// ---------------------------------------------------------------------------
void __fastcall TfrmMain::btnParallelForClick(TObject *Sender)
{
	miTot = 0;
 
	System::Diagnostics::TStopwatch sw = System::Diagnostics::TStopwatch::Create();
	sw.Start();
 
	TParallel::For(NULL, 1, KI_MAX, ParallelIterator);
 
	sw.Stop();
	mmoResults->Lines->Add (String().sprintf(L"Parallel For loop. Time (in milliseconds): %lld, Primes found: %u", sw.ElapsedMilliseconds, miTot));
}
 
 
 
// ---------------------------------------------------------------------------
void __fastcall TfrmMain::ParallelIterator(TObject* Sender, int AIndex)
{
	if (IsPrime(AIndex))
	{
		TInterlocked::Increment((int &) miTot);
	}
}
 
 
 
// ---------------------------------------------------------------------------
bool TfrmMain::IsPrime(unsigned int piN)
{
	unsigned int iTest, iSquare;
	bool bPrime;
 
 
	if (piN <= 3)
	{
		return(piN > 1);
	}
	else if (((piN & 1) == 0) || ((piN % 3) == 0))
	{
		return(false);
	}
	else
	{
		bPrime = true;
		iSquare = sqrt((double) piN);
		iTest = 5;
		while (iTest <= iSquare)
		{
			if (((piN % iTest) == 0) || ((piN % (iTest + 2)) == 0))
			{
				bPrime = false;
				break; // jump out of the for loop
			}
			iTest += 6;
		}
		return(bPrime);
	}
}
//---------------------------------------------------------------------------

cppMain.h

//---------------------------------------------------------------------------
#ifndef cppMainH
#define cppMainH
 
 
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
 
 
//---------------------------------------------------------------------------
class TfrmMain : public TForm
{
__published:	// IDE-managed Components
	TButton *butForLoop;
	TButton *butParallelLoop;
	TMemo *mmoResults;
	void __fastcall btnParallelForClick(TObject *Sender);
	void __fastcall butForLoopClick(TObject *Sender);
private:	// User declarations
	void __fastcall ParallelIterator(TObject* Sender, int AIndex);
public:		// User declarations
	__fastcall TfrmMain(TComponent* Owner);
	bool IsPrime(unsigned int piN);
	unsigned int miTot;
};
 
 
//---------------------------------------------------------------------------
extern PACKAGE TfrmMain *frmMain;
//---------------------------------------------------------------------------
#endif

Os dejo el proyecto, los archivos fuente, y el compilado para descargar directamente aquí (1,1 Mb. en formato ZIP).