せめてMQLにコードを入れてくれれば...。一行一行数えなければならない。
このような作業には、SQLやApache Sparkなどが使用されます。
せめてMQLにコードを入れて欲しい・・・。行ごとに計算する必要があります。
そのような作業には、SQLやApache Sparkなどのオプションを使用します。
まだそこまでの計算はしていません。ただ、配列への書き込みに原因不明の時間がかかるのです(実際はファイルからの読み込みが時間を食っているのですが、メモリについてはまだはっきりとしていません)。
コードに問題があることは否定しない。私はMT4から微調整した(親切なルール)read classを使っています。
配列の宣言、配列をゼロにする、配列のサイズを変更する、ファイルから配列にデータを書き込む、配列から配列にデータを上書きする、配列からファイルにデータを書き込むなど、メインコードはほぼ700行になります。
ここでは、お金が支払われたクラスを紹介します。
//+------------------------------------------------------------------+ //| CSVReader.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property strict //+------------------------------------------------------------------+ //| CSVReader | //+------------------------------------------------------------------+ class CSVReader { private: int m_flags; string m_filename; char m_delimiter; bool m_data_loaded; //--- string m_column_names[]; string m_cells[]; //--- int m_total_rows; int m_total_columns; //--- bool AddData(string data_str,bool header); bool CheckIndexes(int row,int column); string ReplaceCommaByDot(string str); public: CSVReader(string path); //--- void SetDelimiter(char delimiter); void SetCommon(bool common); //--- bool Load(int start_line); //--- string GetStringValue(int row,int column); int GetIntValue(int row,int column); double GetDoubleValue(int row,int column); bool GetBoolValue(int row,int column); //--- int TotalRows() {return(m_total_rows);} int TotalColumns() {return(m_total_columns);} //--- string FileName() {return(m_filename);} //--- string ColumnName(int index); }; //+------------------------------------------------------------------+ //| CSVReader class constructor | //+------------------------------------------------------------------+ void CSVReader::CSVReader(string filename) { m_filename=filename; m_flags=FILE_SHARE_READ|FILE_TXT|FILE_ANSI; m_delimiter=';'; m_data_loaded=false; ArrayResize(m_column_names,0); ArrayResize(m_cells,0); m_total_rows=0; m_total_columns=0; } //+------------------------------------------------------------------+ //| SetDelimiter | //+------------------------------------------------------------------+ void CSVReader::SetDelimiter(char delimiter) { m_delimiter=delimiter; } //+------------------------------------------------------------------+ //| SetCommon | //+------------------------------------------------------------------+ void CSVReader::SetCommon(bool common) { if(common) m_flags|=FILE_COMMON; else m_flags&=~FILE_COMMON; } //+------------------------------------------------------------------+ //| ColumnName | //+------------------------------------------------------------------+ string CSVReader::ColumnName(int index) { if(m_total_columns==0) return(""); if((index>=0) && (index<m_total_columns)) return(m_column_names[index]); return("error"); } //+------------------------------------------------------------------+ //| AddData | //+------------------------------------------------------------------+ bool CSVReader::AddData(string data_str,bool header) { string str=data_str; int DlinaStroki=StringLen(str); int ObrezLeft=StringTrimLeft(str); int ObrezRifgr=StringTrimRight(str); if(ObrezLeft>0) { str=StringSubstr( str, // строка ObrezLeft, // с какой позиции начать DlinaStroki-ObrezLeft // длина извлекаемой строки ); ObrezRifgr=StringTrimRight(str); } if(ObrezRifgr>0) { str=StringSubstr( str, // строка 0, // с какой позиции начать DlinaStroki-ObrezRifgr // длина извлекаемой строки ); } // str=StringTrimLeft(str); // str=StringTrimRight(str); //--- if(StringLen(str)==0) return(false); string lines[]; StringSplit(str,m_delimiter,lines); //--- check ending with delimiter if(StringLen(str)>0) { string str0=StringSubstr(str,StringLen(str)-1,1); //--- ending with delimiter case, decrease lines[] if(str0==CharToString(m_delimiter)) { ArrayResize(lines,ArraySize(lines)-1); } } //--- parse header if(header==true) { m_total_columns=ArraySize(lines); if(m_total_columns==0) return(false); ArrayResize(m_column_names,m_total_columns); //--- for(int i=0; i<m_total_columns; i++) { m_column_names[i]=lines[i]; } } else //--- parse data { int columns_count=ArraySize(lines); //--- add data if(columns_count==m_total_columns) { m_total_rows++; ArrayResize(m_cells,m_total_rows*m_total_columns,10000); //--- for(int i=0; i<columns_count; i++) { int index=m_total_columns*(m_total_rows-1)+i; if((index>=0) && (index<ArraySize(m_cells))) { m_cells[index]=ReplaceCommaByDot(lines[i]); } else return(false); } } } //--- return(true); } //+------------------------------------------------------------------+ //| Load | //+------------------------------------------------------------------+ bool CSVReader::Load(int start_line) { int filehandle=FileOpen(m_filename,FILE_CSV|FILE_READ|FILE_ANSI|FILE_SHARE_READ,'\n'); if(filehandle==INVALID_HANDLE) { Alert("Error in open of file ",m_filename,", error",GetLastError()); return(false); } //--- int line_index=0; while(!FileIsEnding(filehandle)) { string str=FileReadString(filehandle); //--- skip 0th row if(line_index>=start_line) if(str!="") { if(line_index==1) AddData(str,true); else AddData(str,false); } line_index++; } //--- FileClose(filehandle); return(true); } //+------------------------------------------------------------------+ //| ReplaceCommaByDot | //+------------------------------------------------------------------+ string CSVReader::ReplaceCommaByDot(string str) { string str0=""; for(int i=0; i<StringLen(str); i++) { ushort chr=StringGetCharacter(str,i); if(chr==',') chr='.'; str0+=CharToString((uchar)chr); } return(str0); } //+------------------------------------------------------------------+ //| CheckIndexes | //+------------------------------------------------------------------+ bool CSVReader::CheckIndexes(int row,int column) { if((m_total_columns==0) || (m_total_rows==0)) return(false); if((row<0) || (row>=m_total_rows)) return(false); if((column<0) || (column>=m_total_columns)) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| GetStringValue | //+------------------------------------------------------------------+ string CSVReader::GetStringValue(int row,int column) { if(CheckIndexes(row,column)==false) return(""); //--- int index=m_total_columns*row+column; if((index>=0) && (index<ArraySize(m_cells))) return(m_cells[index]); return("error"); } //+------------------------------------------------------------------+ //| GetIntValue | //+------------------------------------------------------------------+ int CSVReader::GetIntValue(int row,int column) { if(CheckIndexes(row,column)==false) return(0); //--- int index=m_total_columns*row+column; if((index>=0) && (index<ArraySize(m_cells))) { return((int)StringToInteger(m_cells[index])); } return(0); } //+------------------------------------------------------------------+ //| GetDoubleValue | //+------------------------------------------------------------------+ double CSVReader::GetDoubleValue(int row,int column) { if(CheckIndexes(row,column)==false) return(0.0); //--- int index=m_total_columns*row+column; if((index>=0) && (index<ArraySize(m_cells))) { return(StringToDouble(m_cells[index])); } return(0.0); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| GetBoolValue | //+------------------------------------------------------------------+ bool CSVReader::GetBoolValue(int row,int column) { if(CheckIndexes(row,column)==false) return(0.0); //--- int index=m_total_columns*row+column; if((index>=0) && (index<ArraySize(m_cells))) { if (StringToInteger(m_cells[index])==1) return (true); else return (false); } return(0.0); } //+------------------------------------------------------------------+
スクリプト(読むことが問題なので、書き込みは省略)は削ぎ落とされたものです。
#property version "1.00" #property indicator_chart_window #property strict //--- #property script_show_inputs #include <CSVReader.mqh> //Класс по чтению информации из файла //#include <CsvWriter_2.mqh> //Класс по записи информации в файл input string FileLoadSetup="PredFind\\Test\\Pred_Ocenka_Read.csv"; input int Prediktor=1; //Целевая input double Support=0.01;//Поддержка input double Relevantnost=70.0;//Достоверность int arrRead_01[]; int arrRead_02[]; int arrRead_03[]; //--Информационные string arrRead_DateTime[]; int arrWrite_01[]; int arrWrite_02[]; int arrWrite_03[]; //--Информационные string arrWrite_DateTime[]; CsvWriter Printer; int Statistic; int StrokTotal=0; int arrSize=0; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { CSVReader FileLoads(FileLoadSetup); FileLoads.SetDelimiter(';'); FileLoads.SetCommon(true); int StrokaSetup=0; if(FileLoads.Load(1)) { StrokTotal=FileLoads.TotalRows(); arrSize=StrokTotal; PrintFormat("File%s loaded. Total rows=%d,Total columns=%d",FileLoads.FileName(),FileLoads.TotalRows(),FileLoads.TotalColumns()); ArrayFree(arrRead_01); ArrayFree(arrRead_02); ArrayFree(arrRead_03); ArrayFree(arrRead_DateTime); ArrayFree(arrWrite_01); ArrayFree(arrWrite_02); ArrayFree(arrWrite_03); ArrayFree(arrWrite_DateTime); //--Зададим размер массивам ArrayResize(arrRead_01,arrSize); ArrayResize(arrRead_02,arrSize); ArrayResize(arrRead_03,arrSize); ArrayResize(arrRead_DateTime,arrSize); ArrayResize(arrWrite_01,arrSize); ArrayResize(arrWrite_02,arrSize); ArrayResize(arrWrite_03,arrSize); ArrayResize(arrWrite_DateTime,arrSize); for(int i=1;i<StrokTotal; i++) { //Print(FileLoads.GetIntValue(i,20)); } for(int i=1;i<StrokTotal; i++) { arrRead_DateTime[i]=FileLoads.GetStringValue(i,0); arrRead_01[i]=FileLoads.GetIntValue(i,1); arrRead_02[i]=FileLoads.GetIntValue(i,2); arrRead_03[i]=FileLoads.GetIntValue(i,3); } } for(int i=1;i<arrSize; i++) { arrWrite_DateTime[i]=arrRead_DateTime[i]; arrWrite_01[i]=arrRead_01[i]; arrWrite_02[i]=arrRead_02[i]; arrWrite_03[i]=arrRead_03[i]; } } //+------------------------------------------------------------------+
もう1つ問題があります。48列を超える書き込み方法がわかりません。私もクラスを利用しています。レコードの列数を増やすために、誰かがクラスを修正するのを手伝ってもらえますか?
これは、に書き込むための前の投稿で欠落しているコードです。
string TimeF= TimeToString ( TimeLocal (), TIME_DATE | TIME_MINUTES ); StringSetCharacter (TimeF, 13 , '_' ); Statistic=Printer.FileCreate( Symbol ()+ "_" + "Pred_Ocenka_Write" , "PredFind\\Test" , false , false ,EvryTick); //Создание файла для записи Printer.Write( "arr_Buy_Sell" , "arr_Vektor_Week" , "arr_Vektor_Day" , "arr_Vektor_Don" , "arr_DonProc" , "arr_iDelta_H_1_H1" , "arr_iDelta_H_1_H3" , "arr_iDelta_H_1_H4" , "arr_iDelta_H_1_H6" , "arr_iDelta_H_1_H12" , "arr_iDelta_H_1_D1" , "arr_iDelta_H_1_W1" , "arr_iDelta_H_1_MN1" , "arr_RSI_Open_M1" , "arr_RSI_Open_H1" , "arr_BB_Center" , "arr_BB_Up" , "arr_BB_Down" , "arr_TimeH" , "arr_Den_Nedeli" , "arr_iDelta_Max_H1" , "arr_iDelta_Min_H1" , "arr_iDelta_Max_D1" , "arr_iDelta_Min_D1" , "arr_Buy Расчетная" , "arr_Buy Номер правила" , "arr_Buy Поддержка" , "arr_Buy Достоверность" ); for ( int i= 1 ;i<arrSize; i++) { Printer.Write( arrRead_DateTime[i], IntegerToString (arrWrite_01[i]), IntegerToString (arrWrite_02[i]), IntegerToString (arrWrite_03[i]), IntegerToString (arrWrite_04[i]), IntegerToString (arrWrite_05[i]), IntegerToString (arrWrite_06[i]), IntegerToString (arrWrite_07[i]), IntegerToString (arrWrite_08[i]), IntegerToString (arrWrite_09[i]), IntegerToString (arrWrite_10[i]), IntegerToString (arrWrite_11[i]), IntegerToString (arrWrite_12[i]), IntegerToString (arrWrite_13[i]), IntegerToString (arrWrite_14[i]), IntegerToString (arrWrite_15[i]), IntegerToString (arrWrite_16[i]), IntegerToString (arrWrite_17[i]), IntegerToString (arrWrite_18[i]), IntegerToString (arrWrite_19[i]), IntegerToString (arrWrite_20[i]), IntegerToString (arrWrite_21[i]), IntegerToString (arrWrite_22[i]), IntegerToString (arrWrite_23[i]), IntegerToString (arrWrite_24[i]), IntegerToString (arrWrite_25[i]), IntegerToString (arrWrite_26[i]), IntegerToString (arrWrite_27[i]), IntegerToString (arrWrite_28[i]), IntegerToString (arrWrite_29[i]), IntegerToString (arrWrite_30[i]), IntegerToString (arrWrite_40[i]), IntegerToString (arrWrite_41[i]), IntegerToString (arrWrite_42[i]), IntegerToString (arrWrite_43[i]), IntegerToString (arrWrite_44[i]), IntegerToString (arrWrite_45[i]), IntegerToString (arrWrite_46[i]), IntegerToString (arrWrite_47[i]), IntegerToString (arrWrite_48[i]), IntegerToString (arrWrite_49[i]), IntegerToString (arrWrite_50[i]), IntegerToString (arrWrite_51[i]), IntegerToString (arrWrite_52[i]), IntegerToString (arrWrite_53[i]), IntegerToString (arrWrite_54[i]), IntegerToString (arrWrite_55[i]), IntegerToString (arrWrite_56[i]) ); }
しかし、ファイルにデータを書き込むためのクラスも支払われます
//+------------------------------------------------------------------+ //| CsvWriter.mqh | //| Виктор Крупинский | //| Krupinskiy@Mail.Ru | //+------------------------------------------------------------------+ #property copyright "Виктор Крупинский" #property link "Krupinskiy@Mail.Ru" #property version "2.00" #property strict enum periodicity { EvryTick=- 1 ,NewBar= PERIOD_CURRENT ,EvryHour= PERIOD_H1 , EvryDay= PERIOD_D1 ,EvryWeek= PERIOD_W1 ,EvryMonth= PERIOD_MN1 }; class CsvWriter { private : int handle; periodicity writeperiod; datetime opentime; bool flag; string DotToComma( string value); public : CsvWriter() { flag= false ; }; ~CsvWriter() { if (flag) FileClose (handle); }; int FileCreate( string fileame, string Dir= "" , bool Common= false , bool FileNew= true ,periodicity period=EvryTick); void FileSelectByHandle( int h,periodicity period=EvryTick) { handle=h; SetPeriodicity(period);}; void SetPeriodicity(periodicity period); int Write( string T1, string T2= "" , string T3= "" , string T4= "" , string T5= "" , string T6= "" , string T7= "" , string T8= "" , string T9= "" , string T10= "" , string T11= "" , string T12= "" , string T13= "" , string T14= "" , string T15= "" , string T16= "" , string T17= "" , string T18= "" , string T19= "" , string T20= "" , string T21= "" , string T22= "" , string T23= "" , string T24= "" , string T25= "" , string T26= "" , string T27= "" , string T28= "" , string T29= "" , string T30= "" , string T31= "" , string T32= "" , string T33= "" , string T34= "" , string T35= "" , string T36= "" , string T37= "" , string T38= "" , string T39= "" , string T40= "" , string T41= "" , string T42= "" , string T43= "" , string T44= "" , string T45= "" , string T46= "" , string T47= "" , string T48= "" , string T49= "" , string T50= "" , string T51= "" , string T52= "" , string T53= "" , string T54= "" , string T55= "" , string T56= "" , string T57= "" , string T58= "" , string T59= "" , string T60= "" , string T61= "" , string T62= "" , string T63= "" ) { int ReturnValue= 0 ; if (writeperiod==- 1 || opentime!=iTime_Old( _Symbol ,writeperiod, 0 )) { if ( FileWrite (handle,DotToComma(T1),DotToComma(T2),DotToComma(T3),DotToComma(T4),DotToComma(T5),DotToComma(T6), DotToComma(T7),DotToComma(T8),DotToComma(T9),DotToComma(T10),DotToComma(T11),DotToComma(T12), DotToComma(T13),DotToComma(T14),DotToComma(T15),DotToComma(T16),DotToComma(T17),DotToComma(T18), DotToComma(T19),DotToComma(T20),DotToComma(T21),DotToComma(T22),DotToComma(T23),DotToComma(T24), DotToComma(T25),DotToComma(T26),DotToComma(T27),DotToComma(T28),DotToComma(T29),DotToComma(T30), DotToComma(T31),DotToComma(T32),DotToComma(T33),DotToComma(T34),DotToComma(T35),DotToComma(T36), DotToComma(T37),DotToComma(T38),DotToComma(T39),DotToComma(T40),DotToComma(T41),DotToComma(T42), DotToComma(T43),DotToComma(T44),DotToComma(T45),DotToComma(T46),DotToComma(T47),DotToComma(T48), DotToComma(T49),DotToComma(T50),DotToComma(T51),DotToComma(T52),DotToComma(T53),DotToComma(T54), DotToComma(T55),DotToComma(T56),DotToComma(T57),DotToComma(T58),DotToComma(T59),DotToComma(T60), DotToComma(T61),DotToComma(T62),DotToComma(T63))) { ReturnValue= 1 ; FileFlush (handle); } } opentime = writeperiod==EvryTick ? 0 : iTime_Old( _Symbol ,writeperiod, 0 ); return (ReturnValue); }; //--------------------------------- End Write ------------------------------------- }; //--------------------- End CsvWriter ------------------------------------------------ int CsvWriter::FileCreate( string filename, string Dir= "" , bool Common= false , bool FileNew= true , periodicity period=EvryTick) { //Print ("Попытка создать файл"); if (FileNew) { //Print ("Новый файл?"); string NextName; int Pos; string Filter = Dir== "" ? "*" : Dir+ "\\*" ; long SearchHandle=Common ? FileFindFirst (Filter,NextName, FILE_COMMON ) : FileFindFirst (Filter,NextName); int Count = StringFind (NextName,filename)>= 0 && (Pos= StringFind (NextName, "_" ))> 0 ? ( int ) StringSubstr (NextName, 0 ,Pos) : 0 ; NextName= "" ; while ( FileFindNext (SearchHandle,NextName)) if ( StringFind (NextName,filename)>= 0 && (Pos= StringFind (NextName, "_" ))> 0 ) Count= MathMax (Count,( int ) StringSubstr (NextName, 0 ,Pos)); FileFindClose (SearchHandle); Count++; filename= IntegerToString (Count, 6 , '0' )+ "_" +filename; } filename = (Dir== "" ? filename : Dir+ "\\" +filename)+ ".csv" ; handle= Common ? FileOpen (filename, FILE_CSV | FILE_COMMON | FILE_READ | FILE_WRITE | FILE_SHARE_READ ) : FileOpen (filename, FILE_CSV | FILE_READ | FILE_WRITE | FILE_SHARE_READ ); // Print ("handle=",handle); flag=handle> 0 ; if (handle> 0 ) { FileSeek (handle, 0 , SEEK_END ); ulong pos= FileTell (handle); SetPeriodicity(period); } return (handle); } //---------------------- End FileCreate ------------------------------------------------ void CsvWriter::SetPeriodicity(periodicity period) { writeperiod = period; opentime = period==EvryTick ? 0 : iTime_Old( _Symbol ,period, 0 ); } //---------------------- End SetPeriodicity -------------------------------------------- string CsvWriter::DotToComma( string value) { int Pos= 0 ; if ((Pos= StringFind (( string )value, "." ))>= 0 && StringFind ( StringSubstr (( string )value,Pos+ 1 ), "." )< 0 ) //value=StringSetChar(value,Pos,','); //Print (value); StringSetCharacter (value,Pos, ',' ); //Print (value); return (value); } //---------------------- End DotToComma ------------------------------------------------ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ datetime iTime_Old( string symbol, int tf, int index) { if (index < 0 ) return (- 1 ); ENUM_TIMEFRAMES timeframe=TFMigrate_Old(tf); datetime Arr[]; if ( CopyTime (symbol,timeframe,index, 1 ,Arr)> 0 ) return (Arr[ 0 ]); else return (- 1 ); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ENUM_TIMEFRAMES TFMigrate_Old( int tf) { switch (tf) { case 0 : return ( PERIOD_CURRENT ); case 1 : return ( PERIOD_M1 ); case 5 : return ( PERIOD_M5 ); case 15 : return ( PERIOD_M15 ); case 30 : return ( PERIOD_M30 ); case 60 : return ( PERIOD_H1 ); case 240 : return ( PERIOD_H4 ); case 1440 : return ( PERIOD_D1 ); case 10080 : return ( PERIOD_W1 ); case 43200 : return ( PERIOD_MN1 ); case 2 : return ( PERIOD_M2 ); case 3 : return ( PERIOD_M3 ); case 4 : return ( PERIOD_M4 ); case 6 : return ( PERIOD_M6 ); case 10 : return ( PERIOD_M10 ); case 12 : return ( PERIOD_M12 ); case 16385 : return ( PERIOD_H1 ); case 16386 : return ( PERIOD_H2 ); case 16387 : return ( PERIOD_H3 ); case 16388 : return ( PERIOD_H4 ); case 16390 : return ( PERIOD_H6 ); case 16392 : return ( PERIOD_H8 ); case 16396 : return ( PERIOD_H12 ); case 16408 : return ( PERIOD_D1 ); case 32769 : return ( PERIOD_W1 ); case 49153 : return ( PERIOD_MN1 ); default : return ( PERIOD_CURRENT ); } }スクリプト全体を添付しました。
78MByteというと、約100万行はあるはずです。
まず、ファイル全体がメモリにコピーされます。そして、int型(8バイト)の配列が4個、行数で掛け合わされます。もちろん、RAMはすぐになくなります。
大きなファイルを扱うには、セクタ単位で読み書きをする必要があるのですが、ここでは不要なメモリまで解放されることはありません。ファイル内の行数は606004行です。
exlleはデータをメモリにコピーしないのですか?
多分、ファイルからデータを読み込む時間が一番長いので、何か他の方法でファイルを処理しなければならないのでしょうが、なぜそうなるのか理解できません。
そうでなければ、読み書きに多くの時間を費やしてしまうからです。
質問ですが、CSVファイルのサイズが78メガバイトで、計算したいのですが、Excelはサイズが大きいので非常に遅いので、MT5を使おうと考えています。
行ごとにデータを配列に読み込むだけのスクリプトを作りました(ファイルからの読み込み用57個、新規ファイルへの書き込み用57個)、配列のサイズはCSVファイルの行数に等しくなります。つまり、Excelが1.5Gバイト以下であるのに対し、スクリプトは8Gバイトのメモリを消費し、MT5では読み込み/書き込みの操作に9分もかかってしまったのです!(笑)。
600 000個の文字列があり、それぞれが最大57個のセルを含み、1次元配列string m_cells[]; に読み込まれる。この配列の文字列要素は3600万個である。文字列 型は、確か空文字列でも12バイトかかる んですよね。すべてのセルを空にしても、サービス(アドレス、文字列長)情報だけで400MBになる。新しい行を1つ追加したときに、この配列のリサイズを行うとどうなるかを見てみましょう。
m_total_rows++;
ArrayResize(m_cells,m_total_rows*m_total_columns,10000)を実行。
- 3600万個の行セルそれぞれについて、十分な長さの空きメモリの塊を見つけ、それをつかみ、値を新しい場所にコピーし、長さを綴らなければなりません。1万要素(またはバイト、私は覚えていません)より多くのメモリが割り当てられたという事実は重要ではありません:1つの行が来るとき、m_total_rowsは再び増加し、m_total_rows*m_total_columnsも、再びコピーによって配列のメモリを再割り当てすることになります。これが、スクリプトに時間がかかる理由です。
32ビットOSでも8バイト単位のチャンクでメモリを確保します。m_cellsは(400+78)MBではなく、1Gbかかると仮定できる。コピーするたびに、m_cellsがすでに占有しているのと同じだけのメモリ領域が必要で、2倍にすると2GBのメモリが必要になる。実際の情報が入っている78MBではなく
全体として、ストリングスセルに格納するのは非常に非効率的な方法なのです。課題がわからないと、これ以上具体的に説明するのは難しい。
ArraySize() とArrayResize()関数を削除してみる - サイズがわかっているのだから。念のため、2倍を目安にお召し上がりください。報告結果
質問ですが、CSVファイルのサイズが78メガバイトで、計算したいのですが、Excelはサイズが大きいので非常に遅いので、MT5を使おうと考えています。
行ごとにデータを配列に読み込むだけのスクリプトを作りました(ファイルからの読み込み用57個、新規ファイルへの書き込み用57個)、配列のサイズはCSVファイルの行数に等しくなります。つまり、Excelが1.5Gバイト以下であるのに対し、スクリプトは8Gバイトのメモリを消費し、MT5では読み込み/書き込みの操作に9分もかかってしまったのです!(笑)。
私も一度、この問題に直面したことがあります。多くの修正を行った。全部は覚えていないのですが、単発の仕事だったんです。
が、ArrayResize(arrRead_01,arrSize); 3パラメータを設定しようとしたところ
|
実験
60万個の文字列があり、それぞれが最大57個のセルを含み、1次元の文字列配列string m_cells[]; つまり3600万個の文字列要素が配列に読み込まれていることになります。文字列 型は、確か空文字列でも12バイトかかる んですよね。すべてのセルを空にしても、サービス(アドレス、文字列長)情報だけで400MBになる。新しい行を1つ追加したときに、この配列のリサイズを行うとどうなるかを見てみましょう。
m_total_rows++;
ArrayResize(m_cells,m_total_rows*m_total_columns,10000)を実行。
- 3600万個の行セルそれぞれについて、十分な長さの空きメモリの塊を見つけ、それをつかみ、値を新しい場所にコピーし、長さを綴らなければなりません。1万要素(またはバイト、私は覚えていません)より多くのメモリが割り当てられたという事実は重要ではありません:1つの行が来るとき、m_total_rowsは再び増加し、m_total_rows*m_total_columnsも、再びコピーによって配列のメモリを再割り当てすることになります。これがスクリプトの遅さの原因です。
コード解析ありがとうございました。
私はOOPを理解するのに苦労しているので、編集をするのは拷問です。私の理解では、読み込みを担当するクラスで、ファイル全体を文字列配列に分割し、必要であれば、この文字列値を別の型に変換して、スクリプトでint型の配列に入れるということです。もし、私の理解が正しければ、処理を速くするためには、ファイル全体を読んで、行と列がいくつあり、各セルに記号がいくつあるかを理解し、それからすぐに配列サイズを選択すればよいのでしょうか。では、どうすればいいのか。
32ビットOSでも8バイト単位のチャンクでメモリを確保します。m_cellsは(400+78)Mbではなく、1Gbを占めると仮定してよいだろう。コピーするたびに、m_cellsがすでに占有しているのと同じだけのメモリ領域が必要で、2倍にすると2GBのメモリが必要になる。実際の情報が入っている78MBではなく
全体として、ストリングスセルに格納するための非常に非効率的な方法である。課題がわからないと、これ以上具体的に説明するのは難しい。
400メガバイトがどこから一気に出てくるのか理解したいのですが?メモリは割り当てられるが、以前に割り当てられたメモリはクリア/解放されないという理解で合っていましたか?

- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
質問ですが、CSVファイルのサイズが78メガバイトで、計算したいのですが、Excelはサイズが大きいので非常に遅いので、MT5を使おうと考えています。
行ごとにデータを配列に読み込むだけのスクリプトを作りました(ファイルからの読み込み用57個、新規ファイルへの書き込み用57個)、配列のサイズは CSVファイルの行数に等しいです。つまり、Excelが1.5ギガバイト以下であるのに対し、スクリプトは8ギガバイトのメモリを消費し、MT5では読み込み/書き込みの操作に9分もかかってしまったのです