Форум: Форум C++Разное
Новые темы: 00
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум C++

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: скорость вывода больших объемов данных
 
 автор: Алекс Кэш   (25.11.2011 в 13:43)   письмо автору
 
 

Возникла необходимость выводить в файл большой объем данных.
При этом довольно критична скорость вывода.
Данные лежат в оперативной памяти таким образом: в контейнере Vector около 1.000.000 элементов, каждый из этих элементов - экземпляр класса ClassStateVector. (привожу его сокращенно).

ClassStateVector
{
public:
ClassStateVector(){};    
        GregTime itsGregTime;
        double itsTsinse;
double itsJDtime;
        double itsX1; double itsX2; double itsX3;
        double itsV1; double itsV2; double itsV3;
        double itsFi; double itsLambda; double itsHight;
        double itsElevation;double itsAzimuth;double itsRange;
double itsLambdaL;double itsFiL;double itsHL;
double itsLambdaP;double itsFiP;double itsHP;
bool itsPriznakVidimosti;
};

class GregTime
    {
public:
       GregTime ()
                {};
       GregTime (int year,int month,int day,int hour,int min,double sec):
itsYear(year),itsMonth(month),itsDay(day),
itsHour(hour),itsMin(min),itsSec(sec)
{};
       GregTime & operator= (const GregTime &); 
       friend std::ostream& operator<<(std::ostream& out, const GregTime& );
       int itsYear;
       int itsMonth;
       int itsDay;
       int itsHour;
       int itsMin;
       double itsSec;
};

надо вывести некоторые поля экземпляров класса (типа double).
если делать стандартно, с помощью потоков

fstream fout(OutFileName);

for (int i=0; i!=Nmas; i++)
        {
        fout << Vecto[i].itsGregTime  ;
fout << Vecto[i].itsAzimuth ;
        fout << Vecto[i].itsElevation ;
        fout << Vecto[i].itsRange ;

        fout << Vecto[i].itsFi;
        fout << Vecto[i].itsLambda;
        fout << Vecto[i].itsHight ;

        fout << Vecto[i].itsFiL*180;
        fout << Vecto[i].itsLambdaL*180;
        fout << Vecto[i].itsHL ;

        fout << Vecto[i].itsFiP*180;
        fout << Vecto[i].itsLambdaP*180;
        fout << Vecto[i].itsHP;

        fout << endl;       
        };

, то получается очень долго. Может быть fprintf() будет работать быстрее? но тогда придется все перегруженные операторы переписывать, есть ли какой то способ ускорить вывод в поток?

  Ответить  
 
 автор: cheops   (25.11.2011 в 13:52)   письмо автору
 
   для: Алекс Кэш   (25.11.2011 в 13:43)
 

Лучший способ, сначала сфомировать содержимое файла в строке, а потом его одной операцией записать её диск. Если строка получается слишком большая, то хотя бы несколько операций. Однако, чем меньше их будет, тем быстрее будет идти дело.

  Ответить  
 
 автор: Алекс Кэш   (25.11.2011 в 17:25)   письмо автору
 
   для: cheops   (25.11.2011 в 13:52)
 

Сделал тестовый вариант по Вашему совету.
fprintf все равно быстрее.
Видимо формировать строку размером 200 Мб (или даже несколько строк поменьше) из моих данных - это долго. Я пытался использовать следущие варианты преобразований:

1. sprintf(szbuff, "%.7g", X);

2. С помощью библиотеки std::stringstream - это вообще кошмар сколько времени занимает (втрое больше!)

Правда только сейчас узнал, что можно использовать библиотеку boost
( boost::lexical_cast<std::string>( значение ) ), может она быстрее преобразует? просто уже надоело разбираться, наверняка все равно fprintf() не побьет.

При этом сам вывод строки действительно проходит быстро, но потери времени на преобразование и формирование строки сводят на нет все преимущество.

К тому же все равно теряется весь смысл использования fout в плане удобства: вывод какой-то кривой получается и сложный.
В итоге решил использовать fprintf - хоть и не очень безопасно и надо код переделывать, но все же удобнее, быстрее, менее затратно в плане оперативки. Или я не прав?

  Ответить  
 
 автор: cheops   (25.11.2011 в 18:09)   письмо автору
 
   для: Алекс Кэш   (25.11.2011 в 17:25)
 

Скорее всего sprintf() окажется самым быстрым вариантом - ведь он не обвешан дополнительным кодом - это даже не C++, а чистая C-функция. Куча операций действительно здорово отнимает время, объект хорошо сохранять на диск, когда он один, когда же им миллионы - зачастую проще сохранить его как есть в виде бинарных данных. Теоретически можно усокрится, если переопределить получатель - т.е. писать не на диск, а в строку, а потом полученную строку уже записывать на диск или организовать буфер, который бы по мере заполнения данных, сбрасывал бы их на диск.

PS Но вообще, как не старайтесь одномоментная запись 200Мб на диск будет занимать время - диск это не очень быстрый девайс не смотря на все SATA-II и SATA-III.

  Ответить  
 
 автор: Алекс Кэш   (25.11.2011 в 19:39)   письмо автору
 
   для: cheops   (25.11.2011 в 18:09)
 

RE:можно усокрится, если переопределить....
я так и делаю (где ////!!!!! в коде стоит), но ускорения все равно нет.
В общем старая добрая fprintf и нет мучений ))

мой тестовый вариант:
здесь выводится Imax чисел типа double (=1000000) , j-тое количество раз (=20) для усреднения.


// test viuvod.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

//#include <cstdlib>
#include <iostream>
#include <time.h>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string.h>


using namespace std;

std::string inline DToStr(double one)
{
    std::stringstream ss;
    ss<<one;
    return ss.str();
}


int main(int argc, char *argv[])
{
    
    const int Jmax=20;const double Imax=1000000;
    clock_t t0, t1, t2, t3;
    double SredneeTime=0;
    int j=0;
    string StrTemp;
    char szbuff[255];
    std::ostringstream ost;
    ofstream fout;       
    

cout << "_________________________________________________\n";
cout << "Programm \"Test\"\n";
cout << "_________________________________________________\n\n";


//-----------------------------------------------------------------------------------
//Potokom
/*
t2 = clock();
for (j=0;j<Jmax;j++)
{
fout.open("TestVivod.fout");
if (fout.fail())

cout << "Can not open (create) Out file: " << "TestVivod.fout" << endl;
std::cout << "_________________________________________________\n";
system("PAUSE");
return 1; 
};

fout << std::setprecision(8) << std::setw(8);

t0 = clock();
//cout << j << " ";
for (double i=0;i<Imax;i++)
      {
        fout << std::setprecision(8) << std::setw(8);
        fout << i << "$";     
        };
fout << endl ;

t1 = clock();
SredneeTime+=(t1-t0);

fout.close();
};

t3 = clock();

cout << "Srednee Time work function fout  = " << (SredneeTime/Jmax) << "  In sek=" << ((SredneeTime/Jmax)/CLOCKS_PER_SEC) << endl
     << "Obwee Time Vivoda Potokom = " << (t3-t2) << "  In sek=" << ((double)(t3-t2)/CLOCKS_PER_SEC) << endl << endl ;
*/


//-----------------------------------------------------------------------------------
//Potokom s perevodom v string

t2 = clock();

for (j=0;j<Jmax;j++)
{
fout.open("TestVivod.foutstring");
if (fout.fail())

cout << "Can not open (create) Out file: " << "TestVivod.fout" << endl;
std::cout << "_________________________________________________\n";
system("PAUSE");
return 1; 
};

t0 = clock();
//cout << j << " ";
for (double i=0;i<Imax;i++)
      {
        sprintf(szbuff, "%.4g", i);
        StrTemp += szbuff;
        //StrTemp=DToStr(i);
        //boost::lexical_cast<std::string>( i ) 
        StrTemp += "$\n";     
        }; 
StrTemp += "\n"

fout << StrTemp ; ////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!

t1 = clock();
SredneeTime+=(t1-t0);

fout.close();
};

t3 = clock();


cout << "Srednee Time work function fout s preobrazovaniem = " << (SredneeTime/Jmax) << "  In sek=" << ((SredneeTime/Jmax)/CLOCKS_PER_SEC) << endl 
     << "Obwee Time Vivoda fout s preobrazovaniem = " << (t3-t2) << "  In sek=" << ((double)(t3-t2)/CLOCKS_PER_SEC) << endl <<endl;



//------------------------------------------------------------------------------------
//fprintfom
t2 = clock();

SredneeTime=0;
FILE *infile;

for (j=0;j<Jmax;j++)
{
infile = fopen("TestVivod.printf""w");
        if (infile == NULL)
       {
       std::cout << "Failed to open file: " << "TestVivod.printf" << "\n";  
   return 2;
   };

t0 = clock();

//printf("j=%i  ",j);
for (double i=0;i<Imax;i++)
      {
        fprintf(infile,"%.4g $\n", i);
        };
fprintf(infile,"\n"); 
 
   
t1 = clock();
SredneeTime+=(t1-t0); 
fclose (infile);

};


t3 = clock();

cout << "Srednee Time work function fprintf = " << (SredneeTime/Jmax) << "  In sek=" << ((SredneeTime/Jmax)/CLOCKS_PER_SEC) << endl 
     << "Obwee Time Vivoda fprintf = " << (t3-t2) << "  In sek=" << ((double)(t3-t2)/CLOCKS_PER_SEC) << endl <<endl;

    system("PAUSE");
    return EXIT_SUCCESS;
}
[code]


а насчет жуткого текстового файла в 200 мб - согласен на 100%.
просто это крайний вариант, такой большой объем данных будет выводиться только в некоторых случаях (но их тоже надо учесть). А смысл в том, что дальше этот файл подхватывает другая прога, и она на Perle, так что бинарный файл она не прочитает.
Или может есть еще какие- то способы передачи данных между прогами на Perle и c++ ?

  Ответить  
 
 автор: cheops   (25.11.2011 в 20:38)   письмо автору
 
   для: Алекс Кэш   (25.11.2011 в 19:39)
 

А что за данные? Может их в бинарном формате удобнее представить? Этот формат будет гораздо короче, а следовательно и выводиться и обрабатываться быстрее.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования