help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fast generation of text file


From: Andy Buckle
Subject: Re: Fast generation of text file
Date: Thu, 2 Jun 2011 11:08:31 +0100

On Wed, Jun 1, 2011 at 10:26 AM, Andy Buckle <address@hidden> wrote:
> On Wed, Jun 1, 2011 at 9:11 AM, wild.manul <address@hidden> wrote:
>> Hello
>>
>> I need to write task for linear programming solver in text file from Octave.
>> The structure of text file is following:
>>
>> a11 x1+ a12 x2+ a13 x3+ ... +a1n xn
>> ....
>> an1 x1+ an2 x2+ an3 x3+ ... +ann xn
>>
>> where a11, ..., ann are given coefficients. x1,...,xn are symbols x with
>> indexes. Coefficients and indexes are stored in matrix a:
>> a11 1 a12 2 a13 3 ... a1n n
>> ....
>> an1 1 an2 2 an3 3 ... ann n
>> Problem is that matrix is rather huge - 2000x2000 elements and writing it to
>> text file is slow.
>>
>> I wrote the following code to do that:
>>
>> for i:row do
>>  fprintf(fid,'%7.5f x%d+',a(i,:));
>> end
>>
>> May be there is faster way how to do it?
>
> I could not figure out a way to make it faster. Some notes, and thoughts:
> - You do not have linebreaks in your fprintf.
> - The looping through fprintf calls can be avoided, but this does not
> help much. I don't know how to have linebreaks if the looping is
> avoided.
> - I tried writing the whole file with one fwrite call, instead of
> fprintf. i did not include this in the example below. This actually
> made it slightly slower.
> - Use a local drive, rather than a network drive.
> - An oct file may make things faster.
>
> my output (for 500x500) on win xp mingw octave 3.2.4 from sf.net:
>                                 no loop: 3.0s
>                                    loop: 3.2s
>                             make string: 10.5s
>     make string (less memory thrashing): 3.2s
>
> my script:
>
> % generate some dummy data
> n=500;
> inds=repmat(1:n,n,1);
> coeffs=rand(n);
> a=zeros(n,2*n);
> a(:,2:2:end)=inds;
> a(:,1:2:end)=coeffs;
>
> % write in one call to fprintf
> tic
> fid=fopen("example1.txt",'w');
> fprintf(fid,'%7.5f x%d+',a');
> fclose(fid);
> printf("%40s: %.1fs\n","no loop",toc);
>
> % loop and call fprintf
> tic
> fid=fopen("example2.txt",'w');
> for i=1:rows(a)
>  fprintf(fid,'%7.5f x%d+',a(i,:));
> end
> fclose(fid);
> printf("%40s: %.1fs\n","loop",toc);
>
> % construct string in memory first
> tic
> s="";
> for i=1:rows(a)
>  s=[s sprintf('%7.5f x%d+',a(i,:))];
> end
> fid=fopen("example3.txt",'w');
> fprintf(fid,"%s",s);
> fclose(fid);
> printf("%40s: %.1fs\n","make string",toc);
>
> % construct string in memory first: less memory thrashing
> chunksize=2^22;
> tic
> s=char(zeros(1,chunksize));
> usedlength=0;
> for i=1:rows(a)
>  append=sprintf('%7.5f x%d+',a(i,:));
>  len=length(append);
>  if length(s)<(usedlength+len)
>        s=[s char(zeros(1,chunksize))]
>  end
>  s(usedlength+1:usedlength+len)=append;
>  usedlength+=len;
> end
> fid=fopen("example4.txt",'w');
> fprintf(fid,"%s",s(1:usedlength));
> fclose(fid);
> printf("%40s: %.1fs\n","make string (less memory thrashing)",toc);

I was curious, so I used an oct file. warning: I am a great c/c++
coder. It may be possible to get this faster still.

For a 700x700 matrix (n=700, in my last script):
                                 no loop: 6.0s
                                    loop: 6.1s
                                oct file: 4.1s

writematrix.cpp:

#include "octave/oct.h"
#include <stdio.h>

DEFUN_DLD (writematrix, args, nargout,
        "example writing formatted output: two arguments, the matrix to
write, then the filename") {
        
        if (args.length()!=2) {
                error("writematrix: two arguments, the matrix to write, then 
the filename");
                return octave_value ();
        }
        
        Matrix a(args(0).matrix_value().transpose());
        double *a_p=a.fortran_vec();
        const double *a_end_p=a_p+a.length();
        std::string filename = args(1).char_matrix_value ().row_as_string(0);
        FILE * pFile;

        pFile = fopen (filename.c_str(),"w");
        
        double *p=a_p;
        while(p < a_end_p) {
                double f=*p++;
                int d=(int)(*p++);
                fprintf(pFile,"%7.5f x%d+",f,d);
        }
        
        fclose (pFile);
        
        return octave_value ();
}



-- 
/* andy buckle */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]