Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading TTask比TThread慢_Multithreading_Delphi_Delphi 10.2 Tokyo - Fatal编程技术网

Multithreading TTask比TThread慢

Multithreading TTask比TThread慢,multithreading,delphi,delphi-10.2-tokyo,Multithreading,Delphi,Delphi 10.2 Tokyo,我有以下两种多线程代码方法来完成相同的工作 任务: 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)

我有以下两种多线程代码方法来完成相同的工作

任务:

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;
输出,例如在29中完成的

TThread:

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


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

这是因为您的线程和任务无法工作

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

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


如果您将睡眠替换为繁忙的工作,在充分利用CPU的情况下运行CPU,那么您将看到这两个版本的性能类似。事实上,我希望基于任务的版本会更好,因为它不会过度订阅处理器

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

您可以尝试以下方法:

TTask.Run(
  procedure()
  begin
  end, TThreadPool.Create);

您的输出与代码不匹配。实际输出是什么?@RemyLebeau输出edited@RepeatUntil编码
Writeln('Thread',ThreadID',started')的意义是什么等等,如果你不打算使用它?注意:这些行的输出对于帮助您理解正在发生的事情非常重要(特别是如果您在输出中包含时间戳)?你确定吗?我不知道
TTask
实现是什么样子的(从您描述的情况来看,它似乎是根据CPU核心自行分配工作的),但是创建80个线程是一个真正的开销(即使上下文切换应该是有效的)。如果Delphi实现本机线程池,它们会更好,但据我所知,它们不会。是的,我确信。与5s睡眠相比,超过80个线程的开销微不足道。我相信公平的上下文切换,但在现实中,除了服务器之外,80个线程并行的实际用途是什么(除了一些可能分布到许多机器上的繁重计算)?在这种情况下,我会考虑本机线程池API实现或队列,而不是简单地创建这么多线程。绝对不要考虑
TTask
是否会带来性能优势。当然,这里的问题是睡眠(因此基准是不正确的)。