我正在读取NetCDF文件,我想在每个数组中读取一个float数组,然后将float数组写入一个新文件。如果我读取float数组然后迭代数组中的每个元素(使用DataOutputStream),我可以使它工作,但这非常非常慢,我的NetCDF文件超过1GB。
我尝试使用ObjectOutputStream,但这会写出额外的信息字节。
所以,回顾一下。 1.打开NetCDF文件 2.从NetCDF文件中读取float数组x 3.只需一步即可将float array x写入原始数据文件 4.用x + 1
重复步骤2答案 0 :(得分:3)
好的,你有1 GB可读和1 GB可写。根据您的硬盘驱动器,您可能会获得大约100 MB / s的读取速度和60 MB / s的写入速度。这意味着读取和写入大约需要27秒。
你看到的驱动器的速度是多少,速度是多少?
如果您想在没有任何处理的情况下测试磁盘的速度,请计算复制最近未访问过的文件所需的时间(即它不在磁盘缓存中)这样可以让您了解磁盘的速度。您可以期望读取的最小延迟然后从文件中写入大部分数据(即不涉及处理或Java)
为了任何想知道如何做一个循环的数据副本的人的利益,即它不只是调用一个为你循环的方法。
FloatBuffer src = // readable memory mapped file.
FloatByffer dest = // writeable memory mapped file.
src.position(start);
src.limit(end);
dest.put(src);
如果您有混合类型的数据,您可以使用ByteBuffer,它一次性地复制一个字节,但实际上可以使用长或更宽的类型一次复制8个或更多字节。即无论CPU能做什么。
对于小块,这将使用循环,但对于大块,它可以使用OS中的页面映射技巧。在任何情况下,它的工作方式都没有在Java中定义,但它可能是复制数据的最快方法。
如果您将已经在内存中的文件复制到缓存文件,那么这些技巧中的大多数只会产生影响。一旦从磁盘读取文件或文件太大而无法缓存物理磁盘的IO带宽,这是唯一真正重要的事情。
这是因为CPU可以将数据以6 GB / s的速度复制到主内存,但只能以60-100 MB / s的速度复制到硬盘驱动器。如果CPU /内存中的副本比可能的速度慢2倍,10倍或50倍,它仍将等待磁盘。注意:没有缓冲这是完全可能的,更糟糕的是,但如果你有任何简单的缓冲,CPU将比磁盘更快。
答案 1 :(得分:1)
1)写作时,使用BufferedOutputStream,你将获得100倍的加速。
2)阅读时,每次读取至少读取10K,可能100K更好。
3)发布你的代码。
答案 2 :(得分:1)
我遇到了同样的问题,并将我的解决方案转储到这里,以备将来的参与。
迭代浮点数组并为每个浮点调用DataOutputStream.writeFloat非常慢。相反,将浮动自身转换为字节数组并一次写入该数组:
慢速:
DataOutputStream out = ...;
for (int i=0; i<floatarray.length; ++i)
out.writeFloat(floatarray[i]);
快得多
DataOutputStream out = ...;
byte buf[] = new byte[4*floatarray.length];
for (int i=0; i<floatarray.length; ++i)
{
int val = Float.floatToRawIntBits(probs[i]);
buf[4 * i] = (byte) (val >> 24);
buf[4 * i + 1] = (byte) (val >> 16) ;
buf[4 * i + 2] = (byte) (val >> 8);
buf[4 * i + 3] = (byte) (val);
}
out.write(buf);
如果您的数组非常大(> 100k),请将其分解为块以避免堆缓冲数组溢出。
答案 3 :(得分:0)
如果你使用Unidata NetCDF library,你的问题可能不是写作,而是NetCDF库缓存机制。
NetcdfFile file = NetcdfFile.open(filename);
Variable variable = openFile.findVariable(variable name);
for (...) {
read data
variable.invalidateCache();
}
答案 4 :(得分:0)
横向解决方案:
如果这是一次性生成(或者如果您愿意在Ant脚本中自动化它)并且您可以访问某种Unix环境,则可以使用NCDUMP而不是在Java中执行它。类似的东西:
ncdump -v your_variable your_file.nc | [awk] > float_array.txt
如果需要,可以使用-p选项控制浮点数的精度。我只是在一个3GB的NetCDF文件上运行它,它工作正常。尽管我喜欢Java,但这可能是你想要的最快捷方式。