1

我已经阅读了很多关于尝试分配超过 1GB 内存的 SO 帖子和一般文章,所以在像其他人一样被击落之前,这里有一些上下文。

此应用程序将作为信息亭运行,专用机器不运行不必要的进程。

我的应用程序以 1920 x 1080 的分辨率和 24 位深度从具有滚动快门的高速相机获取图像,速度为每秒 120 帧。应用程序需要将每一帧写入磁盘以进行后期处理. 我目前面临的问题是磁盘 I/O 无法跟上捕获速率,即使它被限制为每秒 120 帧。所需的磁盘 I/O 带宽约为 750MBps!

原始记录的总长度至少需要 10 秒 (7.5GB)。执行任何即时转码或压缩都会将帧速率降至完全不可接受的水平。

为了解决这个问题,我尝试了以下方法:

  • 通过将硬件级别的位深度降低到 16(仍约为 500MBps)来降低质量。
  • 禁用所有图像编码并将原始相机数据写入磁盘。这节省了一些处理时间。
  • 在磁盘上创建一个 10GB 的文件,并在帧进入时进行顺序写入。到目前为止,这很有帮助。所有开发和生产系统都有一个用于此应用程序的 100GB 专用驱动器。
  • 使用 Sysinternals 的 Contig.exe 对文件进行碎片整理。这在非 SSD 驱动器上取得了惊人的收益。

这里没有可供探索的选择。我不熟悉内存映射文件,在尝试创建它们时,我得到一个 IOException 说Not enough storage is available to process this command.

using (var file = MemoryMappedFile.CreateFromFile(@"D:\Temp.VideoCache", FileMode.OpenOrCreate, "MyMapName", int.MaxValue, MemoryMappedFileAccess.CopyOnWrite))
{
    ...
}

我目前使用的大文件需要顺序写入或顺序读取访问。任何指针将不胜感激。

如果有办法分配这么多 RAM,我什至可以将整体记录大小降低到 1.8GB。再一次,这将在具有 8GB 可用内存和 100GB 可用空间的专用设备上运行。但是,并非所有生产系统都将配备 SSD 驱动器。

4

3 回答 3

1

商品硬件便宜是有原因的。您需要更快的硬件。

购买更快的磁盘系统。一个好的 RAID 控制器和四个 SSD。将驱动器放入 RAID 1+0 配置并解决此问题。

贵公司计划花费多少钱来开发和测试软件以推动廉价硬件超越其限制?即使你能让它运行得足够快,他们打算花多少钱来维护这个软件?

于 2015-07-31T15:22:13.637 回答
1
  1. 内存映射文件不会加快写入文件的速度......

  2. 如果你有一个大文件,你通常不会尝试将它完全映射到 RAM 中......你映射它的“窗口”,然后“移动”窗口(在 C#/Windows API 中,你创建一个“视图”从任何一个位置开始并具有一定大小的文件)

代码示例:(这里的窗口有 1mb 大……更大的窗口是可能的……在 32 位时,应该可以毫无问题地分配 64 或 128mb 的窗口)

const string fileName = "Test.bin";
const long fileSize = 1024L * 1024 * 16;
const long windowSize = 1024 * 1024;

if (!File.Exists(fileName)) {
    using (var file = File.Create(fileName)) {
        file.SetLength(fileSize);
    }
}

long realFileSize = new FileInfo(fileName).Length;

if (realFileSize < fileSize) {
    using (var file = File.Create(fileName)) {
        file.SetLength(fileSize);
    }
}

using (var mm = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open)) {
    long start = 0;

    while (true) {
        long size = Math.Min(fileSize - start, windowSize);

        if (size <= 0) {
            break;
        }

        using (var acc = mm.CreateViewAccessor(start, size)) {
            for (int i = 0; i < size; i++) {
                // It is probably faster if you write the file with
                // acc.WriteArray()
                acc.Write(i, (byte)i);
            }
        }

        start += windowSize;
    }
}

请注意,我在这里编写的代码将写入一个固定的预先知道的字节数(fileSize)...您的代码应该不同(因为您无法预先知道“确切” fileSize)。还记得:内存映射文件不会加快写入文件的速度

于 2015-07-31T16:07:36.280 回答
1

64 位系统上的 32 位进程可以分配 4 GB 的 RAM,因此应该有可能获得 1.8 GB 的 RAM 来存储视频,但当然您需要考虑加载的 DLL 和缓冲区,直到视频被压缩。

除此之外,您可以使用 RAMDisk,例如来自DataRam。您只需要在应用程序需要多少内存和您可以授予磁盘多少内存之间找到一个平衡点。恕我直言,5 GB / 3 GB 设置可以很好地工作:1 GB 用于操作系统,4 GB 用于您的应用程序,3 GB 用于文件。

如果您想要永久保存文件,请不要忘记将文件从 RAM 磁盘复制到 HDD。

于 2015-07-31T17:11:16.380 回答