gpt4 book ai didi

multithreading - Delphi并行编程-多线程速度慢

转载 作者:行者123 更新时间:2023-12-03 15:37:30 25 4
gpt4 key购买 nike

美好的一天,

网络摄像头类每秒大约有 30 帧,所有这些帧都将保存在向量中(如队列)。然后 3 个异步线程将读取队列,并尝试完成其工作(保存这些图像)。为什么队列会溢出?所以问题是这些线程比网络摄像头慢。

Procedure TSaveThread.Execute;
begin
while not terminated do
begin
elElement:=NIL;

EnterCriticalSection(CritSect);
if iElementsLength>=0 then
begin
elElement:=vElements[iElementsLength];
Dec(iElementsLength);
end;
LeaveCriticalSection(CritSect);

if elElement<>NIL then
begin
JpegImg.Assign(elElement.bmWebcam) ;
JpegImg.SaveToFile('Save\'+elElement.sTime+'.jpg') ;
elElement.Free;
end;

Sleep(20);
end;
end;

图像已添加到队列中。

//------------------------------------------------------------------------------
Procedure TWebcam.OnSave(Sender:TObject; bmWebcam:TBitmap);
begin
EnterCriticalSection(CritSect);
inc(iElementsLength);
vElements[iElementsLength]:=TElement.Create(bmWebcam);
LeaveCriticalSection(CritSect);
end;

创建线程。

for i:=0 to 2 do
TSaveThread.Create(false);

问题是,这些线程无法保存所有这些图像。为什么?如何改进我的线程?

德尔福版本:德尔福XE2

网络摄像头帧尺寸:1280x760 或 960x600完整源代码在这里:http://pastebin.com/8SekN4TE

最佳答案

我编写了以下程序:

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils, Vcl.Graphics, Vcl.Imaging.jpeg,
System.IOUtils, System.Diagnostics;

var
i: Integer;
bmp: TBitmap;
jpeg: TJPEGImage;
Stopwatch: TStopwatch;

begin
bmp := TBitmap.Create;
bmp.SetSize(1280, 760);
jpeg := TJPEGImage.Create;
Stopwatch := TStopwatch.StartNew;
for i := 1 to 100 do begin
jpeg.Assign(bmp);
jpeg.SaveToFile('C:\desktop\temp\'+TPath.GetRandomFileName);
end;
Writeln(Stopwatch.ElapsedMilliseconds);
Readln;
end.

它将 1280x760 像素位图转换为 JPEG 图像,然后保存到磁盘。如此反复 100 次。在我的机器上这需要 9 秒。即每秒 11 张图像的吞吐量。如果我跳过转换为 JPEG 步骤并直接保存位图,我可以获得每秒 150 个图像的吞吐量。显然,转换为 JPEG 是一个瓶颈。

您正在寻找每秒 30 张图像。虽然多线程有帮助,但我怀疑你有一台四核机器。一个处理器用于网络摄像头,三个处理器用于保存。因此,如果您只有三个可用线程,那么您可能很难达到每秒 30 帧的所需吞吐量。我的机器上的理论峰值是 33。如果您没有达到每秒 30 帧,那么您的队列显然会溢出。

显而易见的结论是您需要找到更快的 JPEG 转换库。我很确定这样的库存在。例如,我认为 libjpeg 应该快很多。

至于您现有的代码有一些明显的缺陷:

    通常应避免
  1. sleep 。在你的情况下,如果最后一次尝试提取图像成功,那么 sleep 就是自杀。不要那样做。您应该使用真正的线程队列。一种允许对同步对象进行适当阻塞等待的方法。使用事件对象和您最喜欢的非线程队列自己制作一个实际上非常简单。
  2. 您在调用 TElement.Create(bmWebcam) 时保持锁定。这将阻碍扩展。将 TElement.Create(bmWebcam) 分配给锁外部的局部变量。然后分配给锁内部的共享数据。

因此,您可以首先删除对 Sleep 的调用来检查这些想法。然后将 TWebcam.OnSave 更改为如下所示:

Procedure TWebcam.OnSave(Sender:TObject; bmWebcam:TBitmap);
var
NewElement: TElement;
begin
NewElement := TElement.Create(bmWebcam);
EnterCriticalSection(CritSect);
inc(iElementsLength);
vElements[iElementsLength] := NewElement;
LeaveCriticalSection(CritSect);
end;

这些建议会有一点帮助,但我认为您需要解决根本问题,即 JPEG 转换。

关于multithreading - Delphi并行编程-多线程速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13840688/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com