Results 1 to 15 of 15

Thread: Writing numbers to file fast! (Need Faster float to char implementation)

  1. #1
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Writing numbers to file fast! (Need Faster float to char implementation)

    Hi guys, I'd appreciate any insight you have on this.

    What I am doing is capturing data from a data acquisition card working at 200kS/s and saving the data into a double array. Unfortunately I cannot save the data to file before the next lot of data comes in, so I have resorted to saving 30 seconds worth (the largest amount that would fit in my memory) to RAM and then saving it to disk. Its not ideal.

    UPDATE: ________________________
    I have found that most of the time is spent converting the various types into a qbytearray. So I think my question has changed, how can I convert a float (or at worst an int) into a qbytearray (or string) quicker than QString::number or QTextStream << does. Thanks.
    ________________________________

    What I then need to do then is save it to a file. So far I have been using the various QString and QTextStream implementations of "float to string" to find that they take a huge amount of time. Much, much slower than the actual writing to the hard drive (which I thought would be the limiting factor).

    So I decided to do some tests and I found that even writing text to a file (using qtextstream) is pretty slow (note: in a loop). For a float it takes 24 seconds, for a QByteArray with 9 characters it takes 15.7 seconds.

    Now only appending the data to a QByteArray to make one huge array, then writing only takes 3 seconds for a char array but 48s for the float!!! And 24 seconds for an int.

    So, down to business, does anyone know how I could write to a file? I'm willing to try anything, so long as its within my fairly limited programming knowledge.
    Last edited by philwinder; 4th December 2008 at 14:46. Reason: Information update
    Best Regards,
    Phil Winder
    www.philwinder.com

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    First of all don't use a text stream. Instead operate on the file directly, it's faster this way. Second of all try to convert directly to the output format instead of going through many different transformations (like float -> string -> byte array). mmap()ing a file to memory might also help pretty much.

  3. #3
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Quote Originally Posted by wysota View Post
    try to convert directly to the output format instead of going through many different transformations (like float -> string -> byte array).
    How would I go about doing that? By dissecting the current routines?

    Well the fastest I have been able to do it is like this. Basically, multiply all the double data by 1000000 and save as an int. Then do an sprintf and then save that char into a QByte Array. Then iterate over all the data then at the end save to the file using QFile.write

    Qt Code:
    1. double f = 0.54125432;
    2. int num;
    3. QByteArray temp1;
    4. for( int x = 0; x < 200000*30; x++ )
    5. {
    6. num = (int)(f*1000000);
    7. char buf[7];
    8. ::sprintf(buf, "%d", num);
    9. temp1.append( buf );
    10. temp1.append(",");
    11. }
    12. file.write(temp1);
    13. file.flush();
    14. file.close();
    To copy to clipboard, switch view to plain text mode 

    This gets it down to 3.3 seconds, but obviously its a bit annoying having the data in an "int" format. (note: sprintf'ing and double takes about 12 seconds)
    Is that what you meant?
    I'll also have a look at the mmap() function.
    Thanks
    Best Regards,
    Phil Winder
    www.philwinder.com

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Don't expect miracles... working on real values is slow, much slower than working on integers. If you want doubles, you have to cope with bigger delays. You can use an external thread to help you do your work while the other thread is waiting for the data to arrive from the device.

  5. #5
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Of course, I just wondered what was the quickest way to do it. I may even have a look at implementing my own int to string function see if I can shave any more clock cycles off. No doubt there will be lots of redundancy in the sprintf routines...

    Using another thread was on my to do list, but I shyed away from it becuase it seemed to be teeming with potential problems like what happens when the file save thread starts to lag behind the data capture thread. And it looked complicated.

    Hmmm. I may take another look since I have never used threads before and this is as good an excuse as any to have a go.

    Thanks,
    Best Regards,
    Phil Winder
    www.philwinder.com

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    The quickest way to do it is not to convert floats to text

  7. #7
    Join Date
    May 2007
    Posts
    7
    Thanked 2 Times in 2 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    I am not sure is it what you want but please take a look on my example code and decide what should you use to speed you writing up:

    Qt Code:
    1. #include <QTime>
    2. #include <QFile>
    3. #include <QByteArray>
    4. #include <QDebug>
    5.  
    6. #include <iostream>
    7. #include <fstream>
    8.  
    9. int main()
    10. {
    11. const int size = 200000;
    12. {
    13. std::ofstream out("test.txt");
    14. QTime t;
    15. t.start();
    16. double f = 0.54125432;
    17. int num;
    18. for( int x = 0; x < size; x++ )
    19. {
    20. num = (int)(f*1000000);
    21. out << num << ",";
    22. }
    23.  
    24. out.close();
    25. qDebug("Time elapsed: %d ms", t.elapsed());
    26. }
    27.  
    28. {
    29. QFile out("test.txt");
    30. QTime t;
    31. t.start();
    32. double f = 0.54125432;
    33. int num;
    34. QByteArray temp1;
    35. for( int x = 0; x < size; x++ )
    36. {
    37. num = (int)(f*1000000);
    38. char buf[7];
    39. ::sprintf(buf, "%d", num);
    40. temp1.append( buf );
    41. temp1.append(",");
    42. }
    43. out.write(temp1);
    44. out.flush();
    45. out.close();
    46. qDebug("Time elapsed: %d ms", t.elapsed());
    47. }
    48.  
    49. {
    50. std::ofstream out;
    51. out.open("test.bin", std::ios_base::out | std::ios_base::binary);
    52. QTime t;
    53. t.start();
    54. double f = 0.54125432;
    55. double af[size];
    56. for( int x = 0; x < size; x++ )
    57. {
    58. af[x] =f;
    59. }
    60. out.write((const char*)af, size*sizeof(double));
    61. out.close();
    62. qDebug("Time elapsed: %d ms", t.elapsed());
    63.  
    64. memset(af, 0, size);
    65. std::ifstream in;
    66. in.open("test.bin", std::ios_base::in | std::ios_base::binary);
    67. in.read((char*)af, size*sizeof(double));
    68. in.close();
    69. for( int x = 0; x < 10; x++ )
    70. {
    71. qDebug() << x << ": " << af[x];
    72. }
    73. }
    74.  
    75. return 0;
    76. }
    To copy to clipboard, switch view to plain text mode 

    the last part use double array as a buffer. There is also example code how to read your data from file.

  8. The following user says thank you to pgorszkowski for this useful post:

    philwinder (5th December 2008)

  9. #8
    Join Date
    Jan 2006
    Location
    Knivsta, Sweden
    Posts
    153
    Thanks
    30
    Thanked 13 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Quote Originally Posted by wysota View Post
    The quickest way to do it is not to convert floats to text
    Do you have any control over the application that is supposed to read the data you write, i.e. could you write the raw bits that make up the double values without converting them to text and have the reader accept them in that format?

  10. #9
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Do you have any control over the application that is supposed to read the data you write
    Yes I have full control, since I am the only user. At the moment I usually import the data into scilab or matlab to do some math, so I can essentially accept anything that isnt encoded in some wierd encrypted format.

    What were you thinking? Using one of the toHex() routines and write that? Since I dont think sprintf has a binary option?
    Best Regards,
    Phil Winder
    www.philwinder.com

  11. #10
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Quote Originally Posted by pgorszkowski View Post
    I am not sure is it what you want but please take a look on my example code and decide what should you use to speed you writing up
    Thanks pgorszkowski, I will try it later to see if any of those options are quicker. I particually like the look of the std:fstream functions.
    Best Regards,
    Phil Winder
    www.philwinder.com

  12. #11
    Join Date
    Jan 2006
    Location
    Knivsta, Sweden
    Posts
    153
    Thanks
    30
    Thanked 13 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    I was thinking that you could cast a pointer to the first element of your double array to char * and feed it along with the size of the array in bytes to QIODevice::write

  13. The following user says thank you to drhex for this useful post:

    philwinder (5th December 2008)

  14. #12
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Smile Re: Writing numbers to file fast! (Need Faster float to char implementation)

    drhex, pgorszkowski:
    I have now tried your suggestions (you were suggesting the same thing) and they work fantastically. Writing the data to a binary format is many times faster than before.

    The allocation of the array takes about 140ms, which I dont think will get any faster now (although I might try and use QVector to see how that compares - done takes 310 ms). However the more interesting bit is that a QFile::write takes 1 second, whereas the std::ofstream takes 3 seconds. I thought the std function would have been faster, but there you go. Maybe we really are to a point where hard drive speed is the limiting factor.

    By the way, allocating an array then writing the whole array is faster than writing each individual element (1.2 seconds vs 3 seconds) which I guess one would instinctively assume.

    Many thanks to drhex and pgorszkowski and as always, wysota. Cheers.

    P.s.
    For testing and future viewers, here is some cleaned up code with the fastest possible combination:
    Qt Code:
    1. QTime timer;
    2.  
    3. QMessageBox::information(0,"","Ready");
    4. QFile file;
    5. file.setFileName("C:/test.txt");
    6. file.open(QFile::WriteOnly);
    7.  
    8. double f = 0.541263266;
    9.  
    10. int size = 200000*30;
    11. double * af = new double[size];
    12.  
    13. timer.start();
    14. for( int x = 0; x < size; x++ )
    15. af[x] = f;
    16.  
    17. int time = timer.elapsed();
    18. QMessageBox::information(0,"","Elapsed Time: " + QString::number(time) + "ms" );
    19. timer.restart();
    20. file.write((const char*)af, size*sizeof(double));
    21. file.flush();
    22. file.close();
    23. time = timer.elapsed();
    24. QMessageBox::information(0,"","Elapsed Time: " + QString::number(time) + "ms" );
    25. delete [] af;
    To copy to clipboard, switch view to plain text mode 
    Best Regards,
    Phil Winder
    www.philwinder.com

  15. The following user says thank you to philwinder for this useful post:

    Cruz (16th March 2009)

  16. #13
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    With these performance statistics on 30 seconds worth of data (1.2 s), it looks like you might be able to write your data in real time, as opposed to storing 30 seconds worth and then writing. Also would give you some protection against data loss if something fails - can you afford to lose 30 seconds worth of data? Writing in real time, you lose at most a second or so.

    Not that you should think in units of seconds in the first place - if you are sampling a continuous data stream at 200kS/s, then -the smallest- time interval at which you can write in real time without data loss would be better than buffering for some human-defined period like 1, 5, or 30 seconds before writing.

    This is where you might make use of a memory-mapped file. If you know how long you will be acquiring data in total (say 10 minutes), then you allocate the memory-mapped file to a size of 200000 * 600 * sizeof ( double ) and simply acquire to that "array" as if it were the double * array you allocate in your example code. The file system takes care of flushing it to disk at appropriate times (or you can do it manually every second or whatever if you don't trust the file system to do it for you).

    With memory-mapping, you can completely ignore all the details of file I/O except those involved in originally opening and then closing the memory-mapped file. Everything else just looks like filling up an array.

    David

  17. #14
    Join Date
    Jan 2006
    Location
    Knivsta, Sweden
    Posts
    153
    Thanks
    30
    Thanked 13 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    I notice that you tried earlier to multiply your aquired values with 1000000 to get an integer. How much precision does your data have? Using float rather than integer might be sufficient, letting you store twice as many values or write them faster.

  18. #15
    Join Date
    Apr 2008
    Posts
    73
    Thanks
    11
    Thanked 7 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Writing numbers to file fast! (Need Faster float to char implementation)

    Hi guys,
    I have been using the previous routine to save data now for quite a few months, and everything seems to be fine in Real time.

    @d_stranz: Ok, but the reason I had to move to a file anyway was because my system could only handle a minutes worth of data in memory. Since there are 4 channels, sampling at 200kS/s = 800kS/s * 32 bit for float ~= 24.4mB/s. One minute = 1.5 Gig. A lot of data.

    Also, I cannot find a qt related class that deals with it, so would I have to write my own?

    @drhex: Thats was just because I thought that saving an int would be smaller/quicker. I now know that was wrong. The final piece of code is what I have been using. (Or something similar)
    Best Regards,
    Phil Winder
    www.philwinder.com

Similar Threads

  1. qt-3.3.8 fail in scratchbox
    By nass in forum Installation and Deployment
    Replies: 0
    Last Post: 25th May 2007, 15:21
  2. fast writing of large amounts of data to files
    By TheKedge in forum Qt Programming
    Replies: 1
    Last Post: 13th February 2007, 16:33
  3. Writing a XML file
    By Djony in forum Qt Programming
    Replies: 7
    Last Post: 5th February 2007, 16:23
  4. Writing to file at specific
    By safknw in forum Qt Programming
    Replies: 3
    Last Post: 1st December 2006, 11:12
  5. XML file writing
    By mbjerkne in forum Qt Programming
    Replies: 2
    Last Post: 24th May 2006, 19:04

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.