スレッド・バンドル

[確認済み] 最終更新日 によって 金, 17 4月 2026    ソース
 

AI生成スレッド・バンドル

POSIXスレッド

今年は、1つのスレッド・バージョンからマルチスレッド・バージョンまでの最大確率関数を、そのコードの最も遅い部分がモデリング・グループIDのインデックス上でループするアーキテクチャ上の前提に基づいて、そのコードの最大確率関数を移植するように任命されました。これは、設計上、ループを通る各反復は残りの部分から独立している必要があります。

ループ時の楽しい問題

  1. 依存自動変数の再初期化に失敗し、
  2. モデリンググループIDでインデックス付けされた複数のグローバルポインタを変更します(jG),
  3. 計算専用のグローバル・メモリー・セグメントを(ID単位で)分離するには、thread_local変数が必要です。

1と3は簡単でした。2で、私はaの概念を含む賢いアルゴリズムを見つけましたTHREAD_BUNDLEシリアルモデリンググループIDのスレッド単位ブロックです。

保証THREAD_BUNDLE 少なくとも2のメモリページサイズを個々のポインタのサイズで割った大きさで、我々は異なるスレッドが独立して動作することを保証することができますページ 仮想メモリでは、これらのメモリ書き込みで相互排他ロックをエシェウできます。(もちろん、スレッドがそのスレッドを処理すると仮定します) THREAD_BUNDLE ほぼ同じ速度で)。

ついに削除しました。”同じ速度” ループを偶数/oddペアに分割することで、少なくとも1つのメモリーを保証します。ページ アクティブを分離THREAD_BUNDLE ループ。

コア・ループ

  /* EVEN */
  for (jG = minG; jG <= numG; jG += 2*THREAD_BUNDLE)
  {
    pthread_t ptid; 3 refs
    arg_t* arg = mal (sizeof(*arg), "arg_t"); 12 refs

#define SET_ARG(foo) arg->foo = (foo) 30 refs

SET_ARG(jG);
    ...

#undef SET_ARG

// rsim_mlf_thread loops over the index bundle
    // from jG to MIN(numG, jG + THREAD_BUNDLE - minG), doing
    // stuff with global data structures also indexed by jG

pthread_create (&ptid, NULL, rsim_mlf_thread, arg);
    PUSH_STACK_ELT(thread_stack, ptid, pthread_t);
  }

{
    pthread_t *ptid; 3 refs
    while (POP_STACK_PTR(thread_stack, ptid, pthread_t) != NULL)
    {
      arg_t* arg; 6 refs
      pthread_join(*ptid, (void**)&arg);
      ...
  }

/* ODD */
  for (jG = THREAD_BUNDLE + minG; jG <= numG; jG += 2*THREAD_BUNDLE)
  {
    pthread_t ptid; 3 refs
    arg_t* arg = mal (sizeof(*arg), "arg_t"); 12 refs
    ...

メモリー・レイアウト