Hola a todos, tengo la siguiente inquietud a un problema que tengo actualmente.
Tengo el siguiente código hecho en DELPHI 7
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Math, DB, DBClient; type TForm1 = class(TForm) Button3: TButton; EditProcesados3: TEdit; procedure Button3Click(Sender: TObject); private { Private declarations } procedure abrirTstringDestino(); procedure abrirTstringMaestra(); procedure similitud(); function comparacion(s1, s2: string): double; public { Public declarations } end; var Form1: TForm1; listaDestino, listaMaestra : TStringList; implementation {$R *.dfm} { TForm1 } function TForm1.comparacion(s1, s2: string): double; //Jaro-winkler var l1, l2, match_distance, matches, i, k, trans: integer; bs1, bs2: array[1..255] of boolean; //used to avoid getmem, max string length is 255 begin l1 := length(s1); l2 := length(s2); fillchar(bs1, sizeof(bs1), 0); //set booleans to false fillchar(bs2, sizeof(bs2), 0); if l1 = 0 then begin if l2 = 0 then begin Result := 1; Exit; end else begin Result := 0; Exit; end; end; match_distance := (max(l1, l2) div 2) - 1; matches := 0; trans := 0; for i := 1 to l1 do begin for k := max(1, i - match_distance) to min(i + match_distance, l2) do begin if bs2[k] then continue; if s1[i] <> s2[k] then continue; bs1[i] := true; bs2[k] := true; inc(matches); break; end; end; if matches = 0 then begin Result := 0; Exit; end; k := 1; for i := 1 to l1 do begin if (bs1[i] = false) then continue; while (bs2[k] = false) do inc(k); if s1[i] <> s2[k] then inc(trans); inc(k); end; trans := trans div 2; result := ((matches / l1) + (matches / l2) + ((matches - trans) / matches)) / 3; end; procedure TForm1.abrirTstringDestino; var i : integer; begin listaDestino := TStringList.Create; for i := 0 to 100000 do listaDestino.Add(IntToStr(Random(1000000))); end; procedure TForm1.abrirTstringMaestra; var i : integer; begin listaMaestra := TStringList.Create; for i := 0 to 100000 do listaMaestra.Add(IntToStr(Random(1000000))); end; procedure TForm1.similitud; var valorMaestra, valorDestino : String; porcentaje : Double; i,j : integer; begin for i := 0 to listaMaestra.Count - 1 do begin Application.ProcessMessages; valorMaestra := listaMaestra[i]; for j := 0 to listaDestino.Count - 1 do begin valorDestino := listaDestino[j]; porcentaje := comparacion(valorMaestra,valorDestino); //Después se procesa end; EditProcesados3.Text := IntToStr(i); end; end; procedure TForm1.Button3Click(Sender: TObject); begin abrirTstringMaestra; abrirTstringDestino; similitud; end; end.
Básicamente lo que hace es almacenar 100000 datos aleatorios en 2 TStringList diferentes. La idea es tomar los datos del primer TStringList y compararlo con cada uno de los datos del segundo TStringList. Pasándolos por el algoritmo de comparación de similitud de cadenas de texto Jaro-winkler. El proceso lo hace bien y los resultados son correctos.
El inconveniente es el tema del rendimiento ya que para el ejercicio que se va a realizar son con aproximadamente 500000 registros o mas y es en este procedimiento donde se ve afectado el programa en cuanto a tiempo se refiere:
procedure TForm1.similitud; var valorMaestra, valorDestino : String; porcentaje : Double; i,j : integer; begin for i := 0 to listaMaestra.Count - 1 do begin Application.ProcessMessages; valorMaestra := listaMaestra[i]; for j := 0 to listaDestino.Count - 1 do begin valorDestino := listaDestino[j]; porcentaje := comparacion(valorMaestra,valorDestino); //Después se procesa end; EditProcesados3.Text := IntToStr(i); end; end;
Mi pregunta es: Sera posible dividir el primer for en 2 o más y que los recorridos se hagan en paralelo para que el proceso se haga en un tiempo menor al inicial. Buscando en foros encontré que se puede realizar con Multithreading. Pero no tengo muy claro como aplicarlo a este ciclo.