用Java编写浮点数组到文件

时间:2011-09-13 17:17:32

标签: java arrays floating-point netcdf

我正在读取NetCDF文件,我想在每个数组中读取一个float数组,然后将float数组写入一个新文件。如果我读取float数组然后迭代数组中的每个元素(使用DataOutputStream),我可以使它工作,但这非常非常慢,我的NetCDF文件超过1GB。

我尝试使用ObjectOutputStream,但这会写出额外的信息字节。

所以,回顾一下。 1.打开NetCDF文件 2.从NetCDF文件中读取float数组x 3.只需一步即可将float array x写入原始数据文件 4.用x + 1

重复步骤2

5 个答案:

答案 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,但这可能是你想要的最快捷方式。

相关问题