在后台线程中运行的代码可以比在Delphi中的主VCL线程中更快吗?

Rob*_*ler 8 delphi performance multithreading vcl timing

如果有人在主VCL线程和后台线程上运行时间代码有很多经验,我想得到一个意见.我有一些代码在主线程上的Delphi 6应用程序中运行一些繁重的字符串处理.每次运行操作时,每个操作的时间在i5 Quad内核的单个线程上徘徊大约50 ms.让我真正怀疑的是,我在旧Pentium 4上运行的相同代码显示了同样的操作时间,因为通常我看到Pentium 4上运行的代码比Quad Core慢4倍.我开始怀疑代码是否可能消耗的时间远远少于50毫秒但是主要的VCL线程,可能是Windows消息处理或执行Windows API调用,正在为操作创建一个人为的"底层".注意,如果重要,则由套接字上的传入请求触发操作,但是在完全接收数据之前不会进行时间测量.

在我开始将所有代码移到后台线程进行测试之前,我想知道是否有人对此领域有任何一般知识?您在主VCL线程上运行代码的经历是什么?注意,当测试期间绝对没有用户触发的活动时,正在进行定时测量.

我也想知道如果将线程的优先级提高到实时性以下是否会有任何好处.在尝试使用这些标志时,我的运行时间从未见过太多改进.

- roschler

Cos*_*und 12

鉴于所有线程具有与通常相同的优先级,因此存在差异,原因如下.如果您看到了不同之处,请重新评估代码(确保在VCL和后台线程中运行相同的内容)并确保正确计时:

  • 编译器生成完全相同的代码,它不关心代码是在主线程还是后台线程中运行.实际上,您可以将整个代码放在一个过程中,并从您的工作线程Execute()和主VCL线程调用它.

  • 对于CPU,所有内核和所有线程都是相同的.除非它实际上是一个超线程CPU,并非所有核心都是真实的,但随后会看到下一个子弹.

  • 即使并非所有CPU核心都相同,您的线程也不太可能在同一核心上运行,操作系统可以随意移动它(并且实际上安排您的线程在不同时间运行在不同的核心上).

  • 消息传递开销与主VCL线程无关,因为除非您Application.ProcessMessages()手动调用,否则在您的过程执行操作时,消息泵将被停止.消息泵是被动的,您的线程需要从队列中请求消息,但由于线程忙于完成您的工作,因此它不会请求任何消息,因此不会产生任何开销.

只有一个地方线程不相等,这可以改变感知的执行速度:它是将线程调度到执行单元(核心)的操作系统,并且操作系统线程具有不同的优先级.您可以告诉操作系统某个线程需要使用SetThreadPriority()API(TThread.Priority属性使用)进行不同的处理.


Arn*_*hez 10

如果没有简单的源代码来重现问题,以及如何为线程计时,则很难理解软件中发生的情况.

听起来确实如下:

  • 架构问题 - 您的线程是如何定义的?
  • 测量问题 - 你如何计算你的线程?
  • 内存管理器和RTL字符串相关实现的典型扩展问题.

关于最新点,请考虑以下事项:

  • 当前的内存管理器(FastMM4)在多核CPU上的扩展性不佳; 尝试使用每线程内存管理器,就像我们的实验性SynScaleMM一样 - 注意例如Free Pascal编译器团队最近从头开始编写了一个新的缩放MM,以避免这种问题;
  • 尝试更改字符串进程实现以避免内存分配(使用静态缓冲区)和字符串引用计数(每个字符串引用计数访问产生的数据LOCK DEC/INC在多代码CPU上不能很好地扩展 - 使用每个线程的char级进程,使用例如PChar静态缓冲区代替string).

我确信没有string操作,你会发现所有线程都是等价的.

简而言之:既不是当前的Delphi MM,也不是当前的字符串实现在多核CPU上都能很好地扩展.您刚刚发现了当前RTL的已知问题.阅读这个问题.


Nat*_*Nat 6

当您的代码控制VCL线程时,例如,如果它在一个方法中并且没有调用任何VCL控件或调用Application.ProcessMessages,那么运行时不会因为它在主VCL线程中而受到影响.

没有开销,因为当您使用自己的代码时,您"拥有"线程的整个处理能力.

我建议您使用分析工具来查找实际瓶颈的位置.