gpt4 book ai didi

c# - Xeon/nVidia Quadro 机器上的 WPF BitmapImage 创建速度极慢

转载 作者:太空宇宙 更新时间:2023-11-03 22:56:11 24 4
gpt4 key购买 nike

我写了一个 WPF 程序,它是事物的图形浏览器。它在 ListView 中显示相当多的图像,每个图像都有图像控件。它还允许用户进行基本的图像编辑。

我在许多不同的机器上运行过这个软件:我的开发笔记本电脑、我同事的带有并行桌面的 MacBook、可以通过 Windows 远程桌面访问的 VirtualBox VM,甚至在 10 年前的笔记本电脑上。它运行良好。

不幸的是,我们的第一个客户是设计公司,他们拥有为 CAD 设计构建的工作站,配备 Xeon 处理器和 nVidia Quadro 2000 显卡。现在震惊来了:我的程序在他们的机器上运行速度太慢以至于无法使用。

我用过 dotTrace,发现瓶颈是我的 ImageToImageSourceConverter,这是最标准的:

  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Bitmap bmp = value as Bitmap;
if (bmp == null)
return null;

using (MemoryStream memory = new MemoryStream())
{
memory.Seek(0, SeekOrigin.Begin);
bmp.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}

dotTrace 显示,在他们的机器上,带有 bitmapImage.EndInit() 的行占用了大部分计算时间。它也是在 ui 线程上完成的,因此应用程序会卡住一段时间。 dotTrace 告诉调用在 clr.dll 中结束

按比例显示:在我的笔记本电脑上,此转换大约需要 5-10 毫秒,具体取决于位图。在他们的机器上(所有机器!)大约需要 800 毫秒,有时甚至更多。

在其他机器上这不是问题:它运行速度快,卡住不明显。更重要的是,显示的位图非常小 (200x200px),当我将其更改为异步时,由于线程更改开销,它变慢了。

有人知道为什么会这样吗?

到目前为止我尝试过的事情:

  • 通过 RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly 禁用硬件渲染; - 没有区别
  • 更新显卡驱动程序:无差异
  • 禁用显卡驱动程序和窗口兼容模式中的所有加速:没有区别
  • 以管理员身份运行 (why I did this):运行速度明显加快,但仍然不够。

问题很大:如果这不会运行得更快,我们就不会得到报酬 :D

更奇怪的是,有时它只工作几秒钟。

我的笔画是以这样一种方式实现的,即按下按钮的 onMouseMove 我创建了先前图像的副本,并使用从上一个鼠标位置到新鼠标位置的预览颜色绘制额外的线,并跟踪这些点。当您释放 LMB 时,我会在原始图像上绘制具有目标颜色的点之间的线条。它可能看起来很慢,但在我测试的每台机器上都快得惊人。

在他们那里,当您单击并等待片刻,然后移动鼠标时,它会顺利运行。但是,当您立即单击并移动鼠标时,它会卡住并在单击位置和最后位置之间绘制直线,因为它不会在两者之间注册点。

那么,这是否与缓慢加载某些dll然后在一段时间不使用时释放它有关?如果是这样,它会是哪一个?

工作站规范: 英特尔(R) 至强(R) CPU E5-1650 0 @ 3.20GHz NVIDIA Quadro 2000 1GB 16 GB 内存

最佳答案

按照@Clemens 的建议,我更改了Bitmap 和ImageSource 之间的转换方法。这是我的新转换器:

  [ValueConversion(typeof(Bitmap), typeof(ImageSource))]
public class BitmapToImageSourceConverter : IValueConverter
{

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Bitmap bitmap = value as Bitmap;
if (bitmap == null)
return null;

var bitmapData = bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

var bitmapSource = BitmapSource.Create(
bitmapData.Width, bitmapData.Height, 96, 96, ConvertPixelFormat(bitmap.PixelFormat), null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);

bitmap.UnlockBits(bitmapData);
return bitmapSource;
}

private static System.Windows.Media.PixelFormat ConvertPixelFormat(System.Drawing.Imaging.PixelFormat sourceFormat)
{
switch (sourceFormat)
{
case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
return PixelFormats.Bgr24;

case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
return PixelFormats.Bgra32;

case System.Drawing.Imaging.PixelFormat.Format32bppRgb:
return PixelFormats.Bgr32;

// .. as many as you need...
}
return new System.Windows.Media.PixelFormat();
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

这种方法在某些计算机上平均速度甚至快 20 倍。我的测量表明,它在几乎每台机器上都在 1 毫秒内完成转换,而之前的转换器总是在 5 毫秒以上,而且这在 5 到 50 台计算机之间有所不同,有时甚至像我在问题中所说的 800 毫秒。

关于c# - Xeon/nVidia Quadro 机器上的 WPF BitmapImage 创建速度极慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45263691/

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