Ir al contenido


Foto

Procesos en Paralelo


  • Por favor identifícate para responder
1 respuesta en este tema

#1 maurixio5540

maurixio5540

    Member

  • Miembros
  • PipPip
  • 31 mensajes
  • LocationColombia

Escrito 07 octubre 2021 - 09:35

Hola a todos, tengo la siguiente inquietud a un problema que tengo actualmente.

Tengo el siguiente código hecho en DELPHI 7


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls, Math, DB, DBClient;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button3: TButton;
  12. EditProcesados3: TEdit;
  13. procedure Button3Click(Sender: TObject);
  14. private
  15. { Private declarations }
  16. procedure abrirTstringDestino();
  17. procedure abrirTstringMaestra();
  18. procedure similitud();
  19. function comparacion(s1, s2: string): double;
  20.  
  21. public
  22. { Public declarations }
  23. end;
  24.  
  25. var
  26. Form1: TForm1;
  27. listaDestino, listaMaestra : TStringList;
  28.  
  29. implementation
  30.  
  31. {$R *.dfm}
  32.  
  33. { TForm1 }
  34.  
  35. function TForm1.comparacion(s1, s2: string): double; //Jaro-winkler
  36. var
  37. l1, l2, match_distance, matches, i, k, trans: integer;
  38. bs1, bs2: array[1..255] of boolean; //used to avoid getmem, max string length is 255
  39. begin
  40. l1 := length(s1);
  41. l2 := length(s2);
  42. fillchar(bs1, sizeof(bs1), 0); //set booleans to false
  43. fillchar(bs2, sizeof(bs2), 0);
  44. if l1 = 0 then
  45. begin
  46. if l2 = 0 then
  47. begin
  48. Result := 1;
  49. Exit;
  50. end
  51. else
  52. begin
  53. Result := 0;
  54. Exit;
  55. end;
  56. end;
  57. match_distance := (max(l1, l2) div 2) - 1;
  58. matches := 0;
  59. trans := 0;
  60. for i := 1 to l1 do
  61. begin
  62. for k := max(1, i - match_distance) to min(i + match_distance, l2) do
  63. begin
  64. if bs2[k] then
  65. continue;
  66. if s1[i] <> s2[k] then
  67. continue;
  68. bs1[i] := true;
  69. bs2[k] := true;
  70. inc(matches);
  71. break;
  72. end;
  73. end;
  74. if matches = 0 then
  75. begin
  76. Result := 0;
  77. Exit;
  78. end;
  79. k := 1;
  80. for i := 1 to l1 do
  81. begin
  82. if (bs1[i] = false) then
  83. continue;
  84. while (bs2[k] = false) do
  85. inc(k);
  86. if s1[i] <> s2[k] then
  87. inc(trans);
  88. inc(k);
  89. end;
  90. trans := trans div 2;
  91. result := ((matches / l1) + (matches / l2) + ((matches - trans) / matches)) / 3;
  92. end;
  93.  
  94. procedure TForm1.abrirTstringDestino;
  95. var i : integer;
  96. begin
  97. listaDestino := TStringList.Create;
  98. for i := 0 to 100000 do
  99. listaDestino.Add(IntToStr(Random(1000000)));
  100. end;
  101.  
  102. procedure TForm1.abrirTstringMaestra;
  103. var i : integer;
  104. begin
  105. listaMaestra := TStringList.Create;
  106. for i := 0 to 100000 do
  107. listaMaestra.Add(IntToStr(Random(1000000)));
  108. end;
  109.  
  110. procedure TForm1.similitud;
  111. var valorMaestra, valorDestino : String;
  112. porcentaje : Double;
  113. i,j : integer;
  114. begin
  115. for i := 0 to listaMaestra.Count - 1 do
  116. begin
  117. Application.ProcessMessages;
  118. valorMaestra := listaMaestra[i];
  119. for j := 0 to listaDestino.Count - 1 do
  120. begin
  121. valorDestino := listaDestino[j];
  122. porcentaje := comparacion(valorMaestra,valorDestino); //Después se procesa
  123. end;
  124. EditProcesados3.Text := IntToStr(i);
  125. end;
  126. end;
  127.  
  128. procedure TForm1.Button3Click(Sender: TObject);
  129. begin
  130. abrirTstringMaestra;
  131. abrirTstringDestino;
  132. similitud;
  133. end;
  134.  
  135. 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: 

 


delphi
  1. procedure TForm1.similitud;
  2. var valorMaestra, valorDestino : String;
  3. porcentaje : Double;
  4. i,j : integer;
  5. begin
  6. for i := 0 to listaMaestra.Count - 1 do
  7. begin
  8. Application.ProcessMessages;
  9. valorMaestra := listaMaestra[i];
  10. for j := 0 to listaDestino.Count - 1 do
  11. begin
  12. valorDestino := listaDestino[j];
  13. porcentaje := comparacion(valorMaestra,valorDestino); //Después se procesa
  14. end;
  15. EditProcesados3.Text := IntToStr(i);
  16. end;
  17. 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.


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 4.009 mensajes
  • LocationMadrid - España

Escrito 08 octubre 2021 - 07:39

Efectivamente puedes utilizar hilos.
 
Te pongo un ejemplo de como usar hilos para completar bucles paralelos
 


delphi
  1. unit Unit2;
  2.  
  3. interface
  4.  
  5. uses
  6. Classes, Windows;
  7.  
  8. type
  9. TMyThread = class(TThread)
  10. private
  11. Fini, Ffin: integer;
  12. protected
  13. procedure Execute; override;
  14. public
  15. constructor Create(CreateSuspended: Boolean; ini, fin: integer);
  16. end;
  17.  
  18. implementation
  19.  
  20. constructor TMyThread.Create(CreateSuspended: Boolean; ini, fin: integer);
  21. begin
  22. inherited Create(CreateSuspended);
  23. FIni:= ini;
  24. FFin:= fin;
  25. FreeOnTerminate:= true;
  26. end;
  27.  
  28. procedure TMyThread.Execute;
  29. begin
  30. while Fini <= Ffin do
  31. begin
  32. if FFin < 20 then Beep(1000, 100)
  33. else Beep(500, 100);
  34. inc(FIni);
  35. end;
  36. end;
  37.  
  38. end.

El hilo cuenta desde Ini a Fin y genera un sonido de frecuencia distinta según una condición. Esto lo pongo para demostrar que los hilos corren paralelos al oír pitidos diferentes.

Lo sihuiente es una muestra de como usarlo. en este caso creo los hilos suspendidos y se ponen en marcha después.


delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3. uno,dos: TMyThread;
  4. begin
  5. uno:= TMyThread.Create(true, 0, 10);
  6. dos:= TMyThread.Create(true, 11, 20);
  7. uno.Resume;
  8. dos.Resume;
  9. end;

Saludos.


  • 1