3
votes

I have tried to write a parallel threading example using AsyncCalls and the following is to parallel compute the number of prime numbers

program Project3;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Math,
  Windows,
  AsyncCalls in 'AsyncCalls.pas';

const
  N = 1000000;
  MAXT = 100;

var
  threads : array of IAsyncCall;
  ans: array of integer;
  cnt: DWORD;
  i, v, j, k, portion: integer;

function IsPrime(x: integer): boolean;
var
  i: integer;
begin
  if (x <= 1) then 
  begin
    Result := False;
    Exit;
  end;
  if (x = 2) then
  begin
    Result := True;
    Exit;
  end;
  for i:= 2 to Ceil(Sqrt(x))do
  begin
    if (x mod i = 0) then
    begin
      Result := False;
      Exit;
    end;
  end;
  Result := True;
end;

procedure DoWork(left, right: integer; value: PInteger); cdecl;
var
  i, cnt: integer;
begin
  cnt := 0;
  for i := left to right do
  begin
    if (IsPrime(i)) then
    begin
      Inc(cnt);
    end;
  end;
  value^ := cnt;
end;

begin
  // Paralell
  cnt := GetTickCount;
  SetLength(ans, MAXT);
  SetLength(threads, MAXT);
  portion := N div MAXT;
  for i := 0 to MAXT - 2 do
  begin
    // left index
    j := i * portion;
    // right index
    k := (i + 1) * portion - 1;
    threads[i] := AsyncCall(@DoWork, [j, k, @ans[i]]);
  end;
  // last thread
  j := (MAXT - 1) * portion;
  threads[MAXT - 1] := AsyncCall(@DoWork, [j, N - 1, @ans[MAXT - 1]]);
  // Join, doesn't seem to wait all
  AsyncMultiSync(threads, True, INFINITE);
  // ****Adding a delay to wait for all threads*****
  // Sleep(1000);
  // Sum the answer
  v := 0;
  for i := 0 to MAXT - 1 do
  begin
    Inc(v, ans[i]);
  end;
  Writeln('Parallel = ', GetTickCount - cnt);
  Writeln('Answer = ', v);  
  // Serial
  cnt := GetTickCount;
  DoWork(0, N - 1, @v);
  Writeln('Serial = ', GetTickCount - cnt);
  Writeln('Answer = ', v);  
  Readln;
end.

Strange behaviour. The AsyncMultiSync does not seem waiting at all. If I do not add Sleep(1000), the output is

Parallel = 172
Answer = 0
Serial = 453
Answer = 78498

If I add Sleep(1000), the output is correct:

Parallel = 1188
Answer = 78498
Serial = 265
Answer = 78498

I tried using threads[i].Sync, and it produces similar results.

Did I miss something here?

The environment is D2007, Windows 10 64-bit Home

1
You don't check the return value of AsyncMultiSync. - LU RD
even with INFINITE parameter? - justyy
Docs says: The function returns when all listed async calls have finished. If Milliseconds is INFINITE the async calls meight be executed in the current thread. The return value is zero when all async calls have finished. Otherwise it is WAIT_FAILED. - LU RD

1 Answers

3
votes

Documentation says not to exceed the maximum number of wait objects, 61.

So you will have to reduce the MaxT constant.