我的代码执行以下操作
我想知道我是否可以保持100开,不打开和关闭它们太多次了。我可以做fopen
w+
aabbcc...zzaabbcc..zz.........aabb...zz
。写完后我设置了开始读取的位置,读完后我将位置设置为开始写入,依此类推。
问题是:
基于评论和讨论,我将讨论为什么我需要在工作中这样做。它也与我的其他帖子有关
how to convert large row-based tables into column-based tables efficently
我有一个生成结果流的计算。到目前为止,结果保存在行存储表中。该表有1M列,每列可长10M。实际上每列是计算产生的一个属性。在计算运行时,我转储并附加表的中间结果。中间结果可以是每列2或3个双值。我想尽快转储,因为它已经消耗了大约16M内存。计算需要更多的记忆。这最终得到如下表
ref = FIRDatabase.database().reference()
self.ref?.child("Entry").queryOrdered(byChild: "uid").queryEqual(toValue: uid).observeSingleEvent(of: .value, with: { [weak self] (snapshot) -> Void in
guard let strongSelf = self else { return }
print(snapshot)
一行数据存储在一起。当我想逐列分析数据时,就会出现问题。所以我必须读取16个字节然后寻找下一行读取16个字节然后继续。有太多的搜索,它比所有列存储在一起要慢得多,所以我可以按顺序读取它们。
我可以减少计算转储次数。但要使后期阅读更有效率。我可能希望将4K数据存储在一起,因为我假设即使我只读取16字节,每个fread也会默认获得4K。但这意味着我需要在内存中缓冲1M * 4k = 4G ...
所以我在考虑是否可以将片段数据合并到更大的块中,如帖子所说
how to convert large row-based tables into column-based tables efficently
所以我想将文件用作离线缓冲区。如果每个文件包含1M的2个双打,我可能需要256个文件才能在合并后获得4K连续数据。在主要计算方面,这项工作可以作为异步方式完成。但我想确保合并开销很小,所以当它并行运行时,它可以在主计算完成之前完成。所以我提出了这个问题。
我想这与基于列的数据库的构建方式非常相关。当人们创造它们时,他们是否有类似的问题?有没有关于它如何在创作中起作用的描述?
答案 0 :(得分:2)
只要系统上打开的最大文件数允许,您就可以使用w+
;这通常是255或1024,并且可以设置(例如在ulimit
上的Unix上)。
但我不太确定这是值得的。
另一方面,每个10M的100个文件是1千兆字节;你可能想尝试一下RAM磁盘。或者使用大型文件系统缓存。
我怀疑通过分析您的具体问题结构可能会节省大量资金。为什么是100个文件?为何10 M?你在做什么样的“合并”?这100个文件总是以相同的顺序和相同的频率访问吗?是否可以将某些数据保存在RAM中,永远不会写入?
所以,你有几个大的缓冲区,比如,
ABCDEFG...
ABCDEFG...
ABCDEFG...
你想要转动它们以便阅读
AAA...
BBB...
CCC...
如果您已经拥有总大小(即,您知道要写入10 GB的数据),则可以使用两个文件执行此操作,预先分配文件并使用fseek()
写入输出文件。使用内存映射文件,这应该非常有效。实际上,行Y,X列为1,000,000,已被转储到文件Y.dat
中的地址16 * X处;你需要把它写成16 *(Y * 1,000,000 + X)到largeoutput.dat
。
实际上,即使在第一次计算时也可以写入数据。或者您可以通过管道进行两个进程通信,一个计算,一个写入行列和列行文件,以便您可以监视每个进程的性能。
坦率地说,我认为增加更多内存和/或快速I / O层(SSD可能?)可以让你获得同样的优势。您的时间也是如此,在完成这项工作后,内存仍然可用。
答案 1 :(得分:0)
是。您可以在不执行开 - 关 - 打开周期的情况下保持打开100个文件。但是,大多数系统对打开文件的数量都有限制。
如果我在写完w / o结束后阅读,我们是否总是阅读所有书面数据
这取决于你。您可以在文件中的任何位置执行fseek goto并从中读取数据。它一直是你和你的逻辑。
这会节省一些开销吗?文件打开和关闭必须有一些开销,但这个开销是否足以保存?
这肯定会节省一些开销,比如额外的不必要的I / O操作,并且在某些系统中,您写入文件的内容不会立即刷新到物理文件,它可能会被定期缓冲和刷新,或者在fclose的时间。
所以,这样的开销会被保存,但是,真正的问题是你通过节省这些开销来实现什么?它如何适合您的应用程序的整体情况?这是在决定逻辑之前必须进行的调用。