mql5言語の特徴、微妙なニュアンスとテクニック - ページ 53

 
多くの文字列を素早く足し算する方法(例:文字列で取引報告書を作成する)
class SUM_STRING
{
protected:
  uchar Data[];
    
public:
  SUM_STRING( const int Reserve = 0 )
  {
    ::ArrayResize(this.Data, 1, Reserve);
  }

  void operator +=( const string Str )
  {
    ::StringToCharArray(Str, this.Data, ::ArraySize(this.Data) - 1);
  }
  
  const string Get( void ) const
  {
    return(::CharArrayToString(this.Data));
  }
};

// Классическое складывание
ulong SumString1( string TmpStr, const int Amount )
{
  const ulong StartTime = GetMicrosecondCount();

  string Str = "";

  for (int i = 0; i < Amount; i++)
    Str += TmpStr;

  return(GetMicrosecondCount() - StartTime);
}

// Быстрое складывание
ulong SumString2( string TmpStr, const int Amount )
{
  const ulong StartTime = GetMicrosecondCount();

  SUM_STRING SumStr(Amount * StringLen(TmpStr) + 1);

  for (int i = 0; i < Amount; i++)
    SumStr += TmpStr;

  const string Str = SumStr.Get();

  return(GetMicrosecondCount() - StartTime);
}

// #property script_show_inputs

input int inLen = 400;    // Длина строки, которую будем добавлять
input int inAmount = 1 e4; // Сколько раз будем складывать

// Как быстро сложить много строк (например, сгенерировать торговый отчет в string)
void OnStart()
{  
  string Str;
  
  StringInit(Str, inLen, 1);
  
  Print(SumString1(Str, inAmount)); // Время классического решения
  Print(SumString2(Str, inAmount)); // Время альтернативного решения
  Print(SumString2(Str, inAmount)); // Почему эта строка всегда выполняется заметно быстрее, чем предыдущая?
}

結果

2748404
12678
10388

250倍の速さ、それが限界じゃない!


HH 赤で示した事実は、どのような形でも説明できない。

 
fxsaber
多くの文字列を素早く足し算する方法(例:文字列で取引報告書を作成する)。

結果

250倍の速さ、それが限界じゃない!


ZSの赤は、どうにも説明のつかない事実を示しています。

メモリプールの特殊性ですが、SumString2を初めて呼び出したとき、メモリプールはシステムからのメモリで「飽和」しており、再度呼び出すと、もうシステムからメモリは要求されません。

SumString1 を修正することをお勧めします。

ulong SumString1( string TmpStr, const int Amount )
{
  const ulong StartTime = GetMicrosecondCount();

  string Str;
  StringInit(Str,Amount * StringLen(TmpStr) + 1);            << обеспечим строке приёмный буфер

  for (int i = 0; i < Amount; i++)
    Str += TmpStr;

  return(GetMicrosecondCount() - StartTime);
}
 
イリヤス

メモリプールは特殊で、SumString2 が最初にメモリプールに呼び出されたときは、システムからのメモリで「飽和」し、2回目以降はシステムからメモリが要求されなくなります。

SumString1 を修正することをお勧めします。

ありがとうございました。せめて受信バッファの概念をヘルプに何とか反映していただけないでしょうか。今はStringBufferLenしか なく、説明には何も書かれていません。

 
fxsaber

ありがとうございました。ヘルプで受信バッファの概念だけでも何とか説明していただけないでしょうか。今はStringBufferLenしかなく、その記述は意味をなさない。

これは明らかなことで、我々は文字列のために割り当てられたメモリについて話しているのです。ただ、Elijahの「システムからのメモリ飽和」の説明は、何となく分かりにくいですね)

ところで、ローカル変数 が以前に割り当てられたメモリを使用する、といった特徴も知りませんでした。つまり、1回だけ重い計算をするのでなければ、自分で最適化をする意味はほとんどないことがわかります。このメモリを解放する問題も明確ではありません。実行中に解放されるのか、それとも初期化時のみ解放されるのか?

 
アレクセイ・ナヴォイコフ

これは、文字列に割り当てられたメモリについて話していることは明らかです。ただ、イリヤが「システムからのメモリ飽和」について、非常に複雑な説明をしているんです。)

もちろん、イリヤがコードを引用した時点で理解できる。残念ながら、Helpの中では一言も言っていない。

ちなみに、ローカル変数が 先に確保したメモリを使用する、という具体的な機能は私も知りませんでした。つまり、単一の重い計算を扱わない限り、独自の最適化を作る意味はほとんどないことがわかります。

私はちょうど、文字列を作るのに数秒かかるようなケースに直面しました。しかし、最適化後はミリ秒単位でかかるようになりました。しかし、イリヤの変種はもちろん最速です。もし、私のHelpが完璧であったなら、そのようにすることはなかったでしょう。

 
fxsaber:

もちろん、イリヤがコードを出した時点で理解できる。残念ながら、ヘルプにはそれに関する記述はありません。

文字列を形成するのに数秒かかる、そんなケースに出くわしたばかりだ。しかし、最適化後はミリ秒単位で行われるようになった。しかし、イリヤの変種はもちろん最速です。もし、私たちのHelpが理想的なものであったなら、私はそのようなことはしなかったでしょう。

さて、StringInitと いえば、以前から知られていたことです。私もいつも大容量で使っています。追加する線の正確な長さがわからない場合は、おおよその長さで判断しています。

 

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

ライブラリ: TesterBenchmark

fxsaber, 2017.08.15 19:31

ZS2 各パックの1パス目で1648のブレーキがかかるのはなんで?1643年当時はこのよう な状態でした。

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

mql5言語の特徴、微妙なニュアンスとコツ

fxsaber さん 2017.08.15 17:16

Agentジョブバンドル(例:シングルテスターの実行)の最初のパスでは、EAの実行から最初のNewTickイベントまでの時間が数秒かかる場合があります。その後のパックの通過では、この時間はゼロになる。

1648でテスターがすぐにNewTickイベントを作るかのように。もちろん、それは間違いです。
 

テスターでは、IsStopped()は常にゼロを返します(falseではありません)。したがって、テスターでこのフラグとExpertRemove() が実際のように相互作用 することを期待するのは間違っています。

 
StringInit(Str);
Str = NULL;

1行目は2行目よりも高速に実行され、結果は同じです。

 

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

ライブラリ: TesterBenchmark

fxsaber さん 2017.09.05 09:36

PositionSelectをPositionGetTicketに置き換えると、バックテストの速度が7%向上するという愚かな結果になりました。

それもネッティングアカウントで!
理由: