2

私は自分のプロジェクト (Linux、ICC、pthreads) のいくつかの計測器を最適化しています。スレッドに一意のインデックスを割り当てるこの手法に関するフィードバックが欲しいので、それを使用してスレッドごとのデータの配列にインデックスを付けることができます。

古い手法では、pthread id に基づいて std::map を使用しますが、可能であればロックとマップ ルックアップを避けたいと思います (かなりの量のオーバーヘッドが発生します)。

これが私の新しいテクニックです:

static PerThreadInfo info[MAX_THREADS]; // shared, each index is per thread

// Allow each thread a unique sequential index, used for indexing into per
// thread data.
1:static size_t GetThreadIndex()
2:{
3:   static size_t threadCount = 0;
4:   __thread static size_t myThreadIndex = threadCount++;
5:   return myThreadIndex;
6:}

コードの後半:

// add some info per thread, so it can be aggregated globally
info[ GetThreadIndex() ] = MyNewInfo();

そう:

1) 2 つのスレッドがまったく同時に作成された場合、4 行目は競合状態になる可能性があるようです。もしそうなら - どうすればこれを回避できますか (できればロックなしで)? ここでアトミックインクリメントがどのように役立つかわかりません。

2) 何らかの形でスレッドごとのインデックスを作成するより良い方法はありますか? スレッドの作成時に TLS インデックスを何らかの方法で事前に生成することでしょうか?

4

3 に答える 3

1

なぜロックの使用を嫌うのですか?競合状態を解決することは、まさに彼らが設計されたものです...

いずれにせよ、pthread_create()の4番目の引数を使用して、スレッドの開始ルーチンに引数を渡すことができます。このように、マスタープロセスを使用して、スレッドを起動するときに増分カウンターを生成し、作成時にこのカウンターを各スレッドに渡して、スレッドごとに一意のインデックスを作成できます。

于 2011-04-02T00:49:50.210 に答える
0

この[pthreads]にタグを付けたことは知っていますが、std::mapを使用する「古い手法」についても言及しました。これにより、C++ でプログラミングしていると思われます。C++11 には std::thread があり、スレッドの作成時に通常の関数パラメーターを介して一意のインデックス (id) をスレッドに渡すことができます。

以下は、N 個のスレッドを作成し、それぞれに 0 から N-1 のインデックスを割り当てる HelloWorld の例です。各スレッドは、「こんにちは」と言ってインデックスを与えるだけです。

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>

inline void sub_print() {}

template <class A0, class ...Args>
void
sub_print(const A0& a0, const Args& ...args)
{
    std::cout << a0;
    sub_print(args...);
}

std::mutex&
cout_mut()
{
    static std::mutex m;
    return m;
}

template <class ...Args>
void
print(const Args& ...args)
{
    std::lock_guard<std::mutex> _(cout_mut());
    sub_print(args...);
}

void f(int id)
{
    print("This is thread ", id, "\n");
}

int main()
{
    const int N = 10;
    std::vector<std::thread> threads;
    for (int i = 0; i < N; ++i)
        threads.push_back(std::thread(f, i));
    for (auto i = threads.begin(), e = threads.end(); i != e; ++i)
        i->join();
}

私の出力:

This is thread 0
This is thread 1
This is thread 4
This is thread 3
This is thread 5
This is thread 7
This is thread 6
This is thread 2
This is thread 9
This is thread 8
于 2011-04-02T23:29:09.870 に答える