汎用クラスライブラリ - バグ、説明、質問、使用上の特徴、提案 - ページ 17

 
アレクセイ・オレシキン

素晴らしい理論的な例です実際に、何千ものトランザクションを操作したことがある人はいますか?

P.S.私は、それがガラクタであり、誰もそれを必要としないことを証明しようとはしていません。リアルトレードのための価値を理解しようとしている。私は一般的な理論家ではなく、純粋な実践家です。

1000トレードとか、10だけとか、そういうことではないんです。重要なのは、10でも100万でも同じように機能する短いコードを書くということです......。
 

CHashMapの 現在の実装について簡単に説明します。

template<typename TKey,typename TValue>
class CHashMap: public IMap<TKey,TValue>
  {
protected:
   int               m_buckets[];                        
   Entry<TKey,TValue>m_entries[];
   int               m_count;
   int               m_free_list;
   int               m_free_count;
   IEqualityComparer<TKey>*m_comparer;
   bool              m_delete_comparer;

     .................................

.................................

}

まず、Entry<TKey,TValue>とは 何かについて説明します。
基本的にはCLinkedListのようなNodeで、これを含んでいます。

- キーとバリューのコンテナに配置
- キーに対応するキャッシュされたハッシュ値 - hash_code
- next - 一方向リストによる衝突を解決するための,次のEntry<TKey,TValue> への "pointer" です.


m_entries[] - 追加されたキーと値、hash_code、next が配置される "セル" の配列。アレイの大きさは容量に相当します。
m_count - m_entries の最初の未使用セルのインデックスを指定する。初期値は0であり、Capacityまで成長し、次にCapacityと全アレイのサイズを増加させながら全アレイをリビルドする。
m_buckets[] - m_entries[] のインデックス配列.初期値は-1である。アレイサイズは容量に相当する。


衝突しない、CHashMap コンテナに一意な値を追加する。

  1. キーでハッシュを計算し、hash_codeを取得する。
  2. m_entries[]にキー、値、hash_codeをインデックスm_countで格納する。(例では衝突がないためnext = -1)
  3. m_entries[]に先ほど追加した要素のインデックス値をhash_code % (ArraySize(m_buckets)) だけm_buckets[]に入れる(これがm_countになる)。
  4. m_countを+1する

CHashMap コンテナのキーで値を取得する。

  1. キーからハッシュを計算し、hash_codeを取得する。
  2. m_buckets[]から、hash_code % (ArraySize(m_buckets)) で、配列m_entries[]のインデックスとなる値を取得する。
  3. 取得したインデックス m_buckets[hash_code % (ArraySize(m_buckets))] を用いて、配列 m_entries[] から値を取得します。

衝突を解決する

異なるキーでは、hash_code_key_1 % (ArraySize(m_buckets)) と hash_code_key_2 % (ArraySize(m_buckets)) が等しいことがある。これを collision と呼ぶ。
m_entries[]に追加されたコリジョンを持つすべての要素は、nextで1連結リストを通してリンクされる(Entry<TKey,TValue> 構造を参照)。
そして、m_buckets[]は常にこの衝突リストの最初の先頭要素のインデックスを指します。
衝突を伴う1つの大きなリストではなく、多くの小さなリストを得ることができます。


衝突、CHashMap コンテナのキーで値を取得する。

  1. キーに対してハッシュを計算し、hash_codeを取得する。
  2. インデックスhash_code % (ArraySize(m_buckets)) を使って、m_entries[]配列から値を取得する。
  3. nextの値が-1になっていないことから、衝突があることがわかります
  4. m_entries[] の要素からなる単一エントリリストを走査し、求められた値と保存されたキーが等しいかどうかを比較する。


CHashMap コンテナから値を削除する。

- m_entries[] のセルを削除する場合、削除は行わず、空きセルとしてマークし、hash_code = -1 とする。
- free cell は、(Entry<TKey,TValue> から同じ next を使って) 自分自身のリストを形成し、m_free_list
-
フリーセルは、コンテナに新しい値を追加するために最初に使用されます。
-m_free_count は、現在のフリーセル数を制御するために使用される


ハッシュテーブルの再構築(容量を増やすための処理):

- 容量が100%になったときのみ、再構築する。
- 次の容量サイズをリストから取得します。

const static int  CPrimeGenerator::s_primes[]=
  {
   3,7,11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919,
   1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591,
   17519,21023,25229,30293,36353,43627,52361,62851,75431,90523,108631,130363,156437,
   187751,225307,270371,324449,389357,467237,560689,672827,807403,968897,1162687,1395263,
   1674319,2009191,2411033,2893249,3471899,4166287,4999559,5999471,7199369
  };

- m_entries[] および m_buckets[] 配列がインクリメントされる。
- m_buckets[]がクリアされ、m_entries[]のデータ(キーに対するキャッシュされたハッシュ値-hash_code)に基づいて完全に再充填される。



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

Generic Class Library - バグ、説明、質問、使用法、提案。

セルゲイ・デジブリク さん 2017.12.09 01:12

CHashMapの 実装を知りました
正直、気に入りました。


いくつかの改善案があります。

1) 私の率直な意見ですが、この実装では、ハッシュテーブルを再構築する際に、初期サイズ3とそれ以降のサイズの両方について、容量の選択がかなり正しくありません。
そうですね、分布の均一化のために素数を選ぶというのは正しいです。
しかし、CPrimeGeneratorの実装は期待に沿うものではなく、素数の抜けがある。
このような「ジェネレータ」の目的は明確で、素数の自動生成で1.2桁の増加率を提供することである。
しかし、これでは係数が小さすぎるのでは?C++でベクトルを扱う場合、この係数はライブラリにもよりますが、通常1.5〜2.0です(演算の平均的な複雑さに強く影響するため)。
この場合、定数係数の後、素数リストの2進法検索で素数に丸めるという 方法が考えられます。
それに初期サイズが3というのは小さすぎる、前世紀に生きているわけではないのだから。

2) 現在、ハッシュテーブルの再構築(Resize)は、容量が100%になったとき(m_entries[]がすべて埋まったとき)にのみ行われています。
このため、あまり均等に配置されていない鍵では、かなりの量の衝突が発生する可能性があります。
オプションとして、ハッシュテーブルの再構築を行うために必要な制限値で100%を削減するフィルファクターの導入を検討する。


 
アレクセイ・オレシキン

実際のところ、数千件のトランザクションを操作したことがある人はいますか?

そう、1パスで数百万回のヒストリーコールは、多くの人が実践しているのです。

 
Vasiliy Sokolov:

オン・フォート・エブリファースト

クリアです。

hftアルゴリズムでオーダーを送る ことと、それを拾って分析することは別物です。これらのハッシュは送信には必要なく、また解析にも必要ない。

だから、悪気はないんです。理論も必要です。

 
アレクセイ・オレシキン

クリアです。

hftアルゴリズムでオーダーを送ることと、後でピックアップして解析することは別物です。送信にはこれらのハッシュは必要ありませんし、解析にも必要ありません。なぜなら、解析されるのはそのようなものではないからです。

だから、悪気はないんです。また、理論も必要です。


食器洗い乾燥機は使わず、スポンジを使っています。
悪気はないんです。食器洗い機なんてダサい、何のためにあるんだ。

 
アレクセイ・オレシキン

クリアです。

hftのアルゴリズムで命令を出すのと、後で解析のために上げるのは別物です。このハッシュは提出するのに必要ありませんし、その後で別のものを解析するので、解析には必要ありません。

だから、悪気はないんです。また、理論も必要です。

何の恨み?松葉杖を書き続けてください。

 
セルゲイ・デジュブリク

現在のCHashMapの 実装について簡単に説明します。

ありがとうございます、ソースコードを解析するときに使ってみます。

 
ワシリー・ソコロフ

何の恨み?松葉杖を書き続けてください。

ここで提供されたお題を使わず、自分が正しいかどうかを理解しようとすることです。普通の連想配列で満足しているが、もっと良くしたいと常々思っている。
 
fxsaber

ありがとうございます。ソースを解析するときに使ってみます。


新しいキーと値のペアを追加する際に、コンテナ内のキーが存在するかどうかのチェックを省略し、最初に実行しました。
でも、そんなことはどうでもいいんです。

 
がないために起こるエラーメッセージに 直面しました。
//+------------------------------------------------------------------+
//| Gets the element at the specified index.                         |
//+------------------------------------------------------------------+
template<typename T>
bool CArrayList::TryGetValue(const int index,T &value) const

ジェネリック全体でこのようなことを修正してください。

理由: