🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2378閲覧

スレッドのプライオリティを効かせたい(マルチコア。sched_setaffinity()でのマスクなし。)

torimingo

総合スコア122

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/11/01 12:26

編集2019/11/16 08:44

マルチスレッド初心者です。
「マルチコア」、「sched_setaffinity()でのマスクなし」という条件だと、プライオリティの低いスレッド(pthread_t)が動いてしまいます。(プライオリティの高いスレッドのスケジューリングポリシーは「FIFO」にしています。)
上記の条件で、プライオリティを効かせるには、どうしたらよいでしょうか?
sched_setaffinity()でマスクすれば、プライオリティが効くのですが、コアを余らせてしまっているような気がして、なにかもったいない気がします。
C++の新しい規格だと対応しているライブラリとかあるのでしょうか。

コードを以下に掲載します。
-DNO_AFFINITYオプションを付加せずにコンパイルすると、アフィニティの設定が効き、プライオリティの設定が効きます。
スーパーユーザで実行すると、thread1_func()が終了してから、thread2_func()が実行されます。(自分の環境だけかもしれませんが)
-DNO_AFFINITYオプションを付加してコンパイルすると、アフィニティの設定がなくなり、プライオリティが効かなくなります。
thread1_func()とthread2_func()は交互に実行されます。
アフィニティの設定をせずに(#ifndef NO_AFFINITYから#endifまでを消去した状態で)プライオリティを効かせるにはどうしたらよいでしょうか。

c++

1#include <iostream> 2#include <pthread.h> 3 4void *thread1_func(void *p) 5{ 6 for(int i = 0; i < 10; ++i) 7 std::cout << "スレッド1\n"; 8} 9 10void *thread2_func(void *p) 11{ 12 for(int i = 0; i < 10; ++i) 13 std::cout << "スレッド2\n"; 14} 15 16int main() 17{ 18#ifndef NO_AFFINITY 19 // アフィニティ 20 cpu_set_t mask; 21 CPU_ZERO(&mask); 22 CPU_SET(0, &mask); 23 24 if(sched_setaffinity(0, sizeof(mask), &mask) == -1){ 25 std::cout << "アフィニティの設定に失敗しました\n"; 26 } 27#endif 28 29 // スレッド 30 pthread_t thread1, thread2; 31 pthread_attr_t attr1, attr2; 32 struct sched_param parm1, parm2; 33 int max_fifo, min_fifo; 34 35 // スレッド1 (プライオリティを高く設定) 36 pthread_attr_init(&attr1); 37 pthread_attr_setinheritsched(&attr1, PTHREAD_EXPLICIT_SCHED); 38 pthread_attr_setschedpolicy(&attr1, SCHED_FIFO); // スケジューリングポリシー 39 max_fifo = sched_get_priority_max(SCHED_FIFO); 40 parm1.sched_priority = max_fifo; 41 pthread_attr_setschedparam(&attr1, &parm1); // プライオリティ 42 pthread_create(&thread1, &attr1, thread1_func, nullptr); 43 44 // スレッド2 (プライオリティを低く設定) 45 pthread_attr_init(&attr2); 46 pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED); 47 pthread_attr_setschedpolicy(&attr2, SCHED_FIFO); // スケジューリングポリシー 48 min_fifo = sched_get_priority_min(SCHED_FIFO); 49 parm2.sched_priority = min_fifo; 50 pthread_attr_setschedparam(&attr2, &parm2); // プライオリティ 51 pthread_create(&thread2, &attr2, thread2_func, nullptr); 52 53 pthread_join(thread1, nullptr); 54 pthread_join(thread2, nullptr); 55 56 return 0; 57}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2019/11/03 14:38

「プライオリティを効かせる」とはどのようなニュアンスでしょうか? 例えば "コア数>スレッド数" の条件下では、プライオリティによらず全スレッドが同時に動いてもなんら不思議ではありません。なお、C++標準規格の範囲内ではプライオリティという概念自体存在しませんので、実行環境依存となります。
torimingo

2019/11/03 22:15

>> 「プライオリティを効かせる」とはどのようなニュアンスでしょうか?  ひとつのスレッドのプライオリティを高くして、コアに優先的に実行してもらうというニュアンスです。 コードを掲載しましたので、ご確認頂けると幸いです。
guest

回答1

0

ベストアンサー

質問全体を通して、スレッドの実行優先度(プライオリティ; priority)について誤解されている印象を持ちます。

  • プライオリティはスレッド実行の 順序 を制御するものではありません。あくまでも次に実行するスレッドの 優先度 を制御するだけですから、個別スレッドに対する順序性について期待するのは誤っています。長い目で見れば、統計的には実行順序を制御しているとは言えるかもしれません。
  • 利用可能なプロセッサコア数がスレッド数よりも多ければ、プライオリティの設定によらず全てのスレッドが同時実行されます。
  • スレッドのプライオリティが意味を持つのは、スレッド数 > プロセッサコア数 となるときです。OS全体でみるとこの状況が一般的ですので、OSのスケジューラは各スレッドのプライオリティやスケジューリングポリシに基づいて、限られたプロセッサコアをスレッドに割り当てていきます。

「マルチコア」、「sched_setaffinity()でのマスクなし」という条件だと、プライオリティの低いスレッド(pthread_t)が動いてしまいます。(プライオリティの高いスレッドのスケジューリングポリシーは「FIFO」にしています。)

前述の通り、2コア以上を利用可能な環境下では、2スレッド間のプライオリティ差異は意味を持ちません。

sched_setaffinity()でマスクすれば、プライオリティが効くのですが、コアを余らせてしまっているような気がして、なにかもったいない気がします。

該当プロセスに対して「1コアのみ利用可能」とアフィニティマスクを設定すれば、同プロセス内で動く2スレッドのプライオリティが意味を持つようになります。

質問内で指摘されているように、計算機資源の有効活用という意味では “もったいない” とも言えますが、そもそも何を目的としてマルチスレッド処理としたのか次第です。計算処理の高速化が目的であれば、自ら計算資源の利用を制限してしまうのはもったいないです。互いに独立した並行処理をスレッドとして分離記述したのであれば、コア数制限により消費電力を抑えるというプラスの効果も(一応)あります。


動作環境はLinuxでしょうか?スケジューリングポリシ SCHED_FIFO の設定には特権が必要なため、通常ユーザではそもそもこの値を設定できません。

スーパーユーザで実行すると、thread1_func()が終了してから、thread2_func()が実行されます。(自分の環境だけかもしれませんが)

偶然です。

-DNO_AFFINITYオプションを付加してコンパイルすると、アフィニティの設定がなくなり、プライオリティが効かなくなります。
thread1_func()とthread2_func()は交互に実行されます。

偶然そのように動いただけです。


C++の新しい規格だと対応しているライブラリとかあるのでしょうか。

C++17現在(C++20でも)ありません。C++標準規格の範囲内では「スレッドのプライオリティ」という概念自体存在しません。プライオリティ制御には、実行環境(OS)依存のAPIを利用します。

投稿2019/11/05 05:55

編集2019/11/05 05:58
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torimingo

2019/11/05 07:42

詳細なご回答をありがとうございました。 >>動作環境はLinuxでしょうか? はい。Linux(Ubuntu)です。 >>利用可能なプロセッサコア数がスレッド数よりも多ければ、プライオリティの設定によらず全てのスレッドが同時実行されます。 了解しました。 コア数>スレッド数である限り、スレッドは同時に実行されるのですね。
yohhoy

2019/11/05 11:06

プライオリティは「スケジューラが次に実行すべきスレッドを選ぶとき、どのスレッドを優遇するか」というヒント情報です。コア数>スレッド数 であれば、全てのスレッドを実行状態とできるため、スケジューラの仕事はありません。 上記は説明用に簡略化してはいますが、「無限の並列度をもつ実行環境」を考えることは並列アルゴリズムの設計・評価において重要な考え方です。
torimingo

2019/11/08 09:12 編集

すみません。 質問なのですが、複数のCPUをひとつのものとして扱うような方法(プロセッサセット?allocation domain?)を用いて、さらに、スレッドの属性に、プロセススコープを適用しても、コア数>スレッド数であれば、スレッドが同時に実行されてしまうのでしょうか。 (LinuxでCPUをひとつのものとして扱う方法がわからず、また、Linuxはプロセススコープに対応していないようなので、自分の環境では試せないのですが・・・) いろいろ理解が追いつかず、すみません・・・。
torimingo

2019/11/08 10:54 編集

すみません。 もうひとつ、やはり、わからないところがあります。 質問に記載したコードを何度実行してみても、thread1_func()が終了してから、thread2_func()が実行されるのですが、もっとたくさん実行したら、いつかは、thread1_func()が終了するまえに、thread2_func()が実行されることがあるのでしょうか・・・?(偶然というのは、そういう意味でしょうか??) thread1_func()内のループ回数を100万回にしても、thread1_func()が終了してから、thread2_func()が実行されてしまいます。
torimingo

2019/11/08 10:23

質問多くて、すみません、お忙しいようでしたら、スルーしてください!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問