zoukankan      html  css  js  c++  java
  • MATLAB中提高fwrite和fprintf函数的I/O性能

    提高fwritefprintf函数的I/O性能

    http://www.matlabsky.com/thread-34861-1-1.html

     

     

    今天我们将讨论下著名的fwrite(fprintf)函数,它们是用来进行二进制(文本)文件写入操作的。由于fwrite函数是底层I/O函数,且使用十分频繁,很多用户会质疑,它怎么可能还有性能提升的空间,要是有MathWorks早就更新了。

     

    Flushing Buffer

     

    不像C/C++语言,在MATLAB中调用fwirtefprintf)函数时,MATLAB会自动刷新(flush)输出缓存(buffer),这一点MATLAB的帮助文档没有正面直接了当的说明,只是在fopen函数中隐晦的涉及

    clip_image001

     

    看到这里,很多用户估计应该猜到了该怎么做了。在写入数据的时候,假如没有缓存(buffer),那么每次调用fwrite函数,就需要进行一次文件写入操作,这种方式将严重降低I/O性能!

     

    下面看一组比较数据,首先我们没有使用缓存方式

    data = randi(250,1e6,1);  % 生成一组数据,用来测试I/O性能

    % 标准形式,没有应用缓存输出 -

    fid = fopen('demo.dat', 'wb'); % w是小写,b表示二进制

    tic, for idx = 1:length(data), fwrite(fid,data(idx)); end, toc

    fclose(fid);

    Elapsed time is 14.983201 seconds.

    消耗了大概15s,下面看看使用缓存的方式

    % 缓存输出模式3

    fid = fopen('demo.dat', 'Wb'); % 注意W是大写,b表示二进制

    tic, for idx = 1:length(data), fwrite(fid,data(idx)); end, toc

    fclose(fid);

    Elapsed time is 5.616357 seconds.

    使用缓存后时间缩短至5.6s,看来效率提高了不少呀!

    我们无法理解MathWorks为什么将fopen默认设置为非缓存模式,但也许有他们的理由吧!不过当您在写大型数据文件的时候,推荐还是使用缓存模式('w')吧!

     

    Chunking I/O

     

    使用缓存进行写操作,其实就是为了减少数据文件的访问次数,因此在MATLAB中,假如先将所有的数据都准备好,然后一次性调用fwrite函数将其写入文件中

    fid = fopen('demo.dat', 'wb'); % 注意是小写w

    tic, fwrite(fid,data); toc

    fclose(fid);

    Elapsed time is 0.034816 seconds.

    可以看出即使是非缓存模式,写入30ms的效率还是很高的。

     

    但是假如我们读写的是网络文件,由于网络原因可能需要较长的时间,此时将大数据拆开成很多小块,然后分块处理是一个明智的选择。

    h = waitbar(0, 'Saving data...', 'Name','Saving data...');

    cN = 100;  % number of steps/chunks

    % Divide the data into chunks (last chunk is smaller than the rest)

    dN = length(data);

    dataIdx = [1 : round(dN/cN) : dN, dN+1];  % cN+1 chunk location indexes

    % Save the data

    fid = fopen('test.dat', 'Wb');

    for chunkIdx = 0 : cN-1

       % Update the progress bar

       fraction = chunkIdx/cN;

       msg = sprintf('Saving data... (%d%% done)', round(100*fraction));

       waitbar(fraction, h, msg);

       % Save the next data chunk

       chunkData = data(dataIdx(chunkIdx+1) : dataIdx(chunkIdx+2)-1);

       fwrite(fid,chunkData);

    end

    fclose(fid);

    close(h);

    总的来说,本文中的技术同时适用于fprintffwrite函数,但是存储和读取二进制文件(fwrite/fread)远远快于文本文件(fprintf/fscanf/textscan),因此如果数据不是为了人为可读,尽量使用二进制保存!

     

    源文档 <http://blog.sina.com.cn/s/blog_61c0518f0101cckt.html>

  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/AI-Algorithms/p/3674463.html
Copyright © 2011-2022 走看看