5

私はライブラリのマルチスレッド実装に取り​​組んでいます。このライブラリの1つのモジュールには、いくつかのグローバル変数があります(プログラムの実行で非常に頻繁に使用されます)。これらの変数へのアクセスをより安全にするために、スレッドローカルストレージ(TLS)キーワードを使用してそれらを宣言しました__declspec(thread)

これがライブラリ外部関数の呼び出しです。この関数は、グローバル変数を持つモジュールを使用します。

for(i = 0; i<n_cores; i++)
    hth[i] = (HANDLE)_beginthread((void(*)(void*))MT_Interface_DimenMultiCells,0,(void*)&inputSet[i]);

このようにして、ライブラリで使用されるすべての変数がスレッドごとに複製されると思います。

x8コアプロセッサでプログラムを実行すると、操作を完了するために必要な時間は、単一プロセスの実装に必要な時間の3分の1を超えることはありません。

1/8に到達するのは不可能だと知っていますが、少なくとも1/6は到達可能だと思いました。

問題は、これらの__declspec(thread)変数がパフォーマンスの低下の原因であるかどうかです。

4

2 に答える 2

6

それらを以前はグローバルであった場所として宣言する__declspec(thread)と、プログラムの意味とそのパフォーマンス特性が変更されます。

変数がグローバルの場合、各スレッドが参照する単一のコピーがありました。ローカルスレッドとして、それぞれの個別のスレッドには独自の変数があり、そのスレッドローカル変数への変更はそのスレッドでのみ表示されます。

本当にスレッドローカルが必要だとすると、スレッドローカル変数の読み取りと書き込みは通常の変数よりもコストがかかるのは事実です。実行に時間がかかる操作に直面した場合は、実行を完全に停止するのが最善の解決策です。この場合、これを行うには2つの明白な方法があります。

  1. 変数をパラメーターとして渡し、スタックに存在するようにします。スタック変数へのアクセスは迅速です。
  2. この変数を頻繁に読み書きする関数がある場合は、関数の開始時にそのコピーを(ローカル変数に)取得し、そのローカル変数で作業してから、戻ったときにスレッドローカルに書き戻します。 。

これらのオプションのうち、通常は前者が優先されます。オプション2には、この変数を使用する別の関数を関数が呼び出すと簡単に適用できないという大きな弱点があります。

オプション1は、基本的にグローバル変数を使用しないことを意味します(スレッドローカルはグローバルの形式です)。

もちろん、コードが実際に何をしているのかについてほとんど何も言っていないので、これはすべて完全に広い範囲に及ぶ可能性があります。パフォーマンスの問題を解決したい場合は、最初にそれがどこにあるかを特定する必要があります。つまり、測定する必要があります。

于 2011-02-22T10:57:31.117 に答える
5

そしてその答えは、アプリケーションのプロファイルを作成し、最も多くの時間が費やされている場所を測定する必要があるということです。TLSデータを頻繁に参照する関数に含まれていることが判明した場合は、「たぶん」が答えになる可能性があります。

自分で作成したコードであっても、パフォーマンスが低下する理由を特定することは一般に非常に困難です。2つの短い段落で説明されているプログラムでリモートで実行することは、さらに困難です。

プロファイルしてから最適化します。

于 2011-02-22T10:23:57.110 に答える