如何优化写入大量文件的时间(从视频中保存帧)

时间:2012-01-12 12:08:23

标签: c++ file-io kinect

背景

我目前正在开发一个小型应用程序,它可以从Microsoft Kinect设备中获取RGB和深度图流,并将它们保存在磁盘上以供将来分析。当我运行程序时,它应将每个帧作为单独的图像输出到磁盘上。

Kinect的帧速率是30fps,但有两个来源所以这个(大约)60fps。如果我天真地尝试在每个帧到达时保存它,我会得到丢帧,如捆绑的freenect/record.c应用程序所示。

我重写了应用程序以使用一个线程来抓取设备中的帧并将它们推送到双端列表(std::deque)的后面。然后有两个线程,每个线程从双端列表的前面弹出帧并将帧保存到磁盘。 当录制关闭时,列表中可能还有大量的帧需要记录,所以在退出之前我们让两个保存线程完成它们的工作直到完成。

现在实际问题

虽然解决了丢帧问题,但对文件系统的写入仍然很慢。有没有什么好方法可以加快磁盘上的文件创建速度? 目前,函数dump_frame如下所示:

static void
dump_frame(struct frame* frame)
{
    FILE* fp;
    char filename[512]; /* plenty of space! */

    sprintf(filename, "d-%f-%u.pgm", get_time, frame->timestamp);

    fp = fopen(filename, "w");
    fprintf(fp, "P5 %d %d 65535\n", frame->width, frame->height);
    fwrite(frame->data, frame->size, 1, fp);
    fclose(fp);
}

我正在运行Fedora 14 x64,所以解决方案只需要将Linux作为操作系统。

2 个答案:

答案 0 :(得分:1)

可能的改进是使用setvbuf明确将fp的缓冲设置为完整:

const size_t BUFFER_SIZE = 1024 * 16;
fp = fopen(filename, "w");
setvbuf(fp, 0, _IOFBF, BUFFER_SIZE)); /* Must be immediately after the open. */
fprintf(fp, "P5 %d %d 65535\n", frame->width, frame->height);
fwrite(frame->data, frame->size, 1, fp);
fclose(fp);

您可以使用不同的缓冲区大小进行分析,以确定哪种提供最佳性能。

答案 1 :(得分:1)

您需要衡量在特定情况下花费时间的内容。是创建多个文件还是实际将图像数据写入磁盘?

当我使用OSX和英特尔SSD X25M 2G在我的本地系统上进行测试时,我注意到在写入多个1MB文件与写入1个多MB文件时写入的差异很大。这可能是由于文件系统的内务管理,并且会因您拥有的文件系统而异。

为了避免内务管理,您可以将所有图像都放在同一个文件中,然后再拆分。但是,您节省的数据需要大约60MB的持续速度,这是非常高的。

如果你有大量内存,另一种方法是创建一个ram磁盘并首先将图像存储在那里,然后将它们移动到持久文件系统。使用6GB ram磁盘,您可以存储大约100秒的视频。