1

200 ~ 6000 文字の 800k 文字列を含む 4 つの辞書があります。メモリにロードすると、約11ギガのメモリが必要になります。データの解析に 2 分、データの出力に 2 分かかります。私が以下で使用しているものよりも速くデータを出力する方法はありますか? 1 秒あたり 20 ~ 31 MB のディスク IO しか得られませんが、ハード ドライブが 800 くらいできることはわかっています。

var hash1 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash2 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash3 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash4 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
....
foreach (var me in mswithfilenames)
{
    filename = me.Key.ToString();
    string filenamef = filename + "index1";
    string filenameq = filename + "index2";
    string filenamefq = filename + "index3";
    string filenameqq = filename + "index4";

    StreamWriter sw = File.AppendText(filenamef);
    StreamWriter sw2 = File.AppendText(filenameq);
    StreamWriter swq = File.AppendText(filenamefq);
    StreamWriter sw2q = File.AppendText(filenameqq);

    for (i = 0; i <= totalinhash; i++)
    {
        if (hashs1[i].ContainsKey(filenamef))
        {
            sw.Write(hashs1[i][filenamef]);
        }
        if (hashs2[i].ContainsKey(filenameq))
        {
            sw2.Write(hashs2[i][filenameq]);
        }
        if (hashs3[i].ContainsKey(filenamefastaq))
        {
            swq.Write(hash4[i][filenamefastaq]);
        }

        if (hash4[i].ContainsKey(filenameqq))
        {
            sw2q.Write(hash4[i][filenameqq]);
        }
    }

    sw.Close();
    sw2.Close();
    sw3.Close();
    sw4.Close();
    swq.Close();
    sw2q.Close();
}
4

4 に答える 4

3

何か測りましたか?読み書きするデータの量が少なくないように思えます。そのため、最初のステップは、その量のデータの読み取り/書き込み速度に関するディスク サブシステムの絶対的なベースラインを確立することです。ファイルの単純な読み取りに続いて、予想されるおおよそのデータ量の新しいファイルに書き込むと、最適化でどこまで行くことができるかがわかります。

コード自体の読み取り/書き込みにそれほど時間がかからないことは問題ないかもしれません。

于 2012-03-28T18:54:22.450 に答える
2

最も高価な部分は I/O です。そして、このループ:

for (i = 0; i <= totalinhash; i++)
{
    if (hashs1[i].ContainsKey(filenamef))
    {
        sw.Write(hashs1[i][filenamef]);
    }
    if (hashs2[i].ContainsKey(filenameq))
    {
        sw2.Write(hashs2[i][filenameq]);
    }
    ...
}

異なるファイル間で交互に実行されます。これにより、おそらく余分な頭の動きが発生し、断片化されたファイルが作成されます (それらのファイルに対する今後のアクションが遅くなります)。

私は使うだろう:

for (i = 0; i <= totalinhash; i++)
{
    if (hashs1[i].ContainsKey(filenamef))
    {
        sw.Write(hashs1[i][filenamef]);
    }
}

for (i = 0; i <= totalinhash; i++)
{
    if (hashs2[i].ContainsKey(filenameq))
    {
        sw2.Write(hashs2[i][filenameq]);
    }
}
...

しかし、もちろん、これを測定する必要があります。たとえば、SSD では大きな違いはなく、機械的なディスクでのみです。

于 2012-03-28T19:56:12.470 に答える
1

Dictionary<int, Dictionary<string, myCustomDataHolder>>4 つの別々のパラレルではなく、1 つのパラレルを使用できますDictionary<int, Dictionary<string, string>か? 消費されるスペースが大幅に削減されるだけでなく、辞書の検索が 1/4 になります。

あなたの質問を考えると、辞書が完全に平行であるかどうかは明確ではありませんが、私には十分に思われます。

于 2012-03-28T18:53:16.300 に答える
0

私はそれを追加したいと思います

if (hashs1[i].ContainsKey(filenamef))
{
   sw.Write(hashs1[i][filenamef]);
}

2 つのハッシュ テーブル アクセスが必要です。1 つは格納キー用で、もう 1 つは実際のアクセス用です。多くのディクショナリ アクセスが追加される可能性があるため、ディクショナリの tryGetValue メソッドを使用してこれらのアクセスを半分にすることができます。これにより、これら 2 つの呼び出しが 1 つに結合されます。これがどのように機能するかを説明できますが、これは私ができるよりもうまく機能します: http://www.dotnetperls.com/trygetvalue

于 2012-05-17T22:40:42.410 に答える