技术堆栈:C#/ .NET 4 / WinForms
背景:
我正在使用的项目是一系列图像堆栈的可视化应用程序。具体地,每个图像堆栈与网格对齐,在任何时间显示相同的图像,并且处理功能应用于当前在视图中的图像。图像堆栈本身为150-300 MB,每个映像为512KB-1MB。典型的数据集将包含~100个图像堆栈。
问题:
为了尝试使用这些数据,我使用了几种技术:
然而,即使使用上述所有内容,重复性仍然有很多不足之处。使用SysInternals Process Explorer,CPU利用率很低(<25%),而内存使用量在垃圾收集发生之前会上升到极限。
分析表明,大部分执行时间都花在从内存映射文件中获取数据上。我假设它等待操作系统将请求的内存页面重新打开到活动内存中?
我还能做些什么来改善表现?
注意:
更新1:
答案 0 :(得分:5)
首先,我认为使用不安全的代码和内存映射文件并不是很有帮助。您需要从磁盘读取大约20GB的数据。如果您只是使用流,那么从磁盘读取它将比内存中的一个额外副本花费更长的时间 - 您已经在错误的位置进行了优化。
我认为你应该从不同的角度来看待它。您可以在显示器上显示少量10MB数据的图像堆栈 - 价值20GB。您不需要读取20GB的数据来显示所有图像堆栈,并在处理这些图像时提供响应式UI。您只需要从每个堆栈加载顶部图像 - 这将更快
。至于实际处理,除非你能以某种方式使用GPU,否则我认为你不能比并行处理图像更快。我想这取决于你实际做的处理。
答案 1 :(得分:2)
当所有图像都可用时,您仍然可以为每个图像预先生成拇指图像,并仅在Grid
上加载它们。在用户将效果/转换应用于图像的那一刻,您可以仅加载 该图像。即使在加载仅该图像时,您也可以将其分配到剪切加载扇区并以异步方式加载它们。如果您查看Google Street View,它是如何加载的,在缩放后,您会发现从不整个图像(即使它是您请求的)立即加载,但是它按扇区加载。
我认为另一种非常有趣的技术,Deep Zoom可能是,如果不是你问题的答案,但至少可以提供一个好的提示。
来自Scott Hanselman的 祝你好运。答案 2 :(得分:0)
听起来很反常,你应该尝试触摸(即从每个文件的开头每4KB读取一个字节)应用程序启动时内存映射文件中的所有数据。由于你有足够的RAM,问题可能不是操作系统正在分页你的图像,而是它最初没有分页。内存映射文件是懒惰加载的,所以操作系统不会在你真正尝试访问内存映射文件中的数据。因此,在应用程序加载时触摸内存将导致磁盘读取发生,而不是用户正在查看映像堆栈时。
答案 3 :(得分:0)
减少并行处理的图像数量以增加内存局部性。 因此,您的4个核心应该同时处理一个图像。 这对处理器缓存很有用。
答案 4 :(得分:0)
根据显示器和图像的大小,您可以尝试下采样图像以适合堆栈所在的方块的分辨率。然后,如果您想要聚焦图像的某个点,则可以重新加载原始图片。
如果您使用的是WPF,可以尝试使用DecodePixelWidth和DecodePixelHeight。也许在winforms中有一个等价物