4

我有以下两种多线程代码方法做同样的工作。

任务:

const
  MaxThreadCount = 80;

procedure TWorkerTask.Update;
var
  aTasks  : array of ITask;
  I: Integer;
begin
  Stopwatch := TStopwatch.StartNew;
  SetLength(aTasks, MaxThreadCount);
  for I := Low(aTasks) to High(aTasks) do begin
    aTasks[I] := TTask.Create( procedure
    begin
      Writeln('Thread ', TTask.CurrentTask.Id, ' Stared');
      Sleep(5000);
      Writeln('Thread ', TTask.CurrentTask.Id, ' Finshed');
    end);
    aTasks[I].Start;
  end;
  TTask.WaitForAll(aTasks);
  Elapsed := Stopwatch.Elapsed;
  Writeln('Done in ', Round(Elapsed.TotalSeconds));
end;

输出例如Done in 29

线程:

const
  MaxThreadCount = 80;

procedure TWorker.Execute;
begin
  Writeln('Thread ', ThreadID, ' Stared');
  Sleep(5000);
  Writeln('Thread ', ThreadID, ' Finshed');
end;

....

var
  Workers   : array of TWorker;
  I         : Integer;
  Stopwatch : TStopwatch;
  Elapsed   : TTimeSpan;  
begin
  SetLength(Workers, MaxThreadCount);
  for I := Low(Workers) to High(Workers) do begin
    Workers[I] := TWorker.Create;
    Workers[I].Start;
  end;
  for I := Low(Workers) to High(Workers) do
    Workers[I].WaitFor;
  Elapsed := Stopwatch.Elapsed;
  Writeln('Done ', Round(Elapsed.TotalSeconds));

输出例如Done 8

问:为什么TTask在上述方法上比TThread类慢得多?有没有办法加快速度以获得类似的结果?

4

2 回答 2

8

这是因为您的线程和任务不起作用。

你有比处理器更多的线程。在使用线程的版本中,您可以为每个任务创建一个线程,尽管处理器被超额订阅,但这并不重要,因为线程正在休眠。

在基于任务的版本中,通常每个处理器有一个线程。因此,并非所有任务都可以同时运行。

如果您用 CPU 满负荷运行的繁忙工作来代替睡眠,那么您会看到两个版本的性能相似。事实上,我希望基于任务的版本会更好,因为它不会超额订阅处理器。

于 2017-06-09T02:05:05.723 回答
0

每个任务不一定意味着 1 个线程。delphi任务系统节省资源,甚至监控CPU使用情况来决定是否创建更多线程。特别是我也发现任务很慢,为了避免这种缓慢,当我需要使用任务时,我只需为每个任务创建一个线程池,因此它与简单的 TThread 具有相同的性能,因为这样你将确保每个任务都会在自己的线程上运行。

你可以尝试这样的事情:

TTask.Run(
  procedure()
  begin
  end, TThreadPool.Create);
于 2020-06-27T13:58:55.143 回答