如何提高多相机设置的写入速度?
How do I increase writing speed for multi camera setup?
我有一个具有顺序写入能力的磁盘 1572 Mb/second
我有 4 个 60 fps 的相机。每帧未编码,是 3.7 Mb(假设为 4 Mb)图像。
我需要的写入速度是4*4*60 = 960Mb/s。
PointGrey 提供示例代码:
for (unsigned int uiCamera = 0; uiCamera < numCameras; uiCamera++)
{
error = retrieveImage(ppCameras[uiCamera], &image);
// error = ppCameras[uiCamera]->RetrieveBuffer(&image);
if (error != PGRERROR_OK)
{
PrintError(error);
cout << "Press Enter to exit." << endl;
cin.ignore();
return -1;
}
// Get the size of the buffer associated with the image, in bytes.
// Returns the size of the buffer in bytes.
iImageSize = image.GetDataSize();
// Write to the file
ardwBytesWritten[uiCamera] = writeFrameToFile(m_ALLCAMS, image);
};
其中:
size_t writeFrameToFile(FILE* f, Image image)
{
return fwrite(image.GetData(),
1,
image.GetCols() * image.GetRows(),
f);
}
不幸的是,在发布模式下我只能获得大约 370 - 500 Mb/s 的写入速度(根据 windows 分析器)。
writeFrameToFile 是最慢的操作,在调试模式下需要 12-13 毫秒。
并行写入文件有意义吗,或者ssd不能并行写入?我应该使用多个 SSD 吗?
谢谢你。
如果您在 Linux 系统上,请考虑将文件映射到内存中。
事先知道文件大小,您可以指示OS使用mmap()
等函数设置显式内存映射。然后文件的全部内容被映射到程序的虚拟内存 space,写入文件就变得像在两个内存缓冲区之间复制数据一样简单。
当然,在写入的过程中,不需要整个文件都在内存中。但是,这就是这种方法的力量。通过让 OS 为您映射内存,通常用于直写缓存和页面预取的相同机制将写入的页面异步转储到磁盘上的实际文件。这样,您的程序可以继续编写,并且 OS 本身会安排 where/when 实际的 I/O 发生(通常在其他 CPU 核心上,而不会暂停您的程序的执行).此外,OS.
也适当地选择了块大小。
TL;DR:
- 文件映射在 Linux 上为您提供强大的异步 I/O。
- 您无需担心缓冲区大小。 OS 为您做出正确的决定。
- 设置起来可能更复杂,但一旦完成,您就可以像写入内存缓冲区一样优雅地写入文件。
有关详细信息,请查看 the manual page and this example on Gist。
编辑: 从评论中,我现在看到您在 Windows。使用 CreateFileMappingA()
. More information can be found in this article.
也可以在那里完成同样的事情
如果没有别的办法,您最后的选择是通过直接写入磁盘本身来绕过 OS 和文件系统。
在 Linux 上,您可以通过写入适当的设备来做到这一点,可能是在 /dev/disk/by-id/... 中的某个地方,而在 Windows 上,我什至不知道去哪里开始,但我相当确定这是可能的。
请注意,这会破坏磁盘上已有的所有内容,因此您只需要一个用于此目的的磁盘,如果您不小心写入了错误的设备,则可能会破坏整个 OS 安装。
所以这是相当高级和冒险的东西,我对它的了解还不够多,无法真正提供帮助,只是说它可能值得研究。
我有一个具有顺序写入能力的磁盘 1572 Mb/second
我有 4 个 60 fps 的相机。每帧未编码,是 3.7 Mb(假设为 4 Mb)图像。 我需要的写入速度是4*4*60 = 960Mb/s。
PointGrey 提供示例代码:
for (unsigned int uiCamera = 0; uiCamera < numCameras; uiCamera++)
{
error = retrieveImage(ppCameras[uiCamera], &image);
// error = ppCameras[uiCamera]->RetrieveBuffer(&image);
if (error != PGRERROR_OK)
{
PrintError(error);
cout << "Press Enter to exit." << endl;
cin.ignore();
return -1;
}
// Get the size of the buffer associated with the image, in bytes.
// Returns the size of the buffer in bytes.
iImageSize = image.GetDataSize();
// Write to the file
ardwBytesWritten[uiCamera] = writeFrameToFile(m_ALLCAMS, image);
};
其中:
size_t writeFrameToFile(FILE* f, Image image)
{
return fwrite(image.GetData(),
1,
image.GetCols() * image.GetRows(),
f);
}
不幸的是,在发布模式下我只能获得大约 370 - 500 Mb/s 的写入速度(根据 windows 分析器)。
writeFrameToFile 是最慢的操作,在调试模式下需要 12-13 毫秒。
并行写入文件有意义吗,或者ssd不能并行写入?我应该使用多个 SSD 吗? 谢谢你。
如果您在 Linux 系统上,请考虑将文件映射到内存中。
事先知道文件大小,您可以指示OS使用mmap()
等函数设置显式内存映射。然后文件的全部内容被映射到程序的虚拟内存 space,写入文件就变得像在两个内存缓冲区之间复制数据一样简单。
当然,在写入的过程中,不需要整个文件都在内存中。但是,这就是这种方法的力量。通过让 OS 为您映射内存,通常用于直写缓存和页面预取的相同机制将写入的页面异步转储到磁盘上的实际文件。这样,您的程序可以继续编写,并且 OS 本身会安排 where/when 实际的 I/O 发生(通常在其他 CPU 核心上,而不会暂停您的程序的执行).此外,OS.
也适当地选择了块大小。TL;DR:
- 文件映射在 Linux 上为您提供强大的异步 I/O。
- 您无需担心缓冲区大小。 OS 为您做出正确的决定。
- 设置起来可能更复杂,但一旦完成,您就可以像写入内存缓冲区一样优雅地写入文件。
有关详细信息,请查看 the manual page and this example on Gist。
编辑: 从评论中,我现在看到您在 Windows。使用 CreateFileMappingA()
. More information can be found in this article.
如果没有别的办法,您最后的选择是通过直接写入磁盘本身来绕过 OS 和文件系统。
在 Linux 上,您可以通过写入适当的设备来做到这一点,可能是在 /dev/disk/by-id/... 中的某个地方,而在 Windows 上,我什至不知道去哪里开始,但我相当确定这是可能的。
请注意,这会破坏磁盘上已有的所有内容,因此您只需要一个用于此目的的磁盘,如果您不小心写入了错误的设备,则可能会破坏整个 OS 安装。
所以这是相当高级和冒险的东西,我对它的了解还不够多,无法真正提供帮助,只是说它可能值得研究。