ページ 11

C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 10:12
by 百合子
こんにちは
C言語のpthread_create(...)を使って、threadをがんがん作成していきたいですが、
Q1: threadの限度数はないでしょうか。
Q2: 生成したthreadは解放を(消滅させ)したりする必要はないでしょうか。

もしOS依存であれば、WindowsとLINUX系を別々にご解説いただければ幸いでございます。

宜しくお願いします。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 10:17
by 百合子
追伸:
pthread_create(...)を使って実行される関数の間まったく順番関係がないでしょうか。
例えば、先にpthread_create(...)で実行された関数は後にpthread_create(...)で実行された関数より後に実行される可能性もありますか。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 15:26
by sleep
百合子 さんが書きました: Q1: threadの限度数はないでしょうか。
参考までに
Windows の限界に挑む: プロセスとスレッド
Linuxにおけるスレッド数の上限

1スレッドあたりに割り当てられるスタックサイズは
・Windows
CreateThread関数で新たなサイズが指定されていない場合、生成されたスレッドはそれを生成したスレッドと同じスタック サイズを受け継ぎます。
メインスレッドのデフォルトスタックサイズは、dumpbin.exeなどで取得可能(上記URL参照のこと:コマンドプロンプト上で dumpbin /headers [exeのパス] で表示される size of stack reserve)

・Linux
pthread_attr_getstacksize関数で取得可能
百合子 さんが書きました: Q2: 生成したthreadは解放を(消滅させ)したりする必要はないでしょうか。
生成したスレッドに実行させていた関数が終了すれば、割り当てられていたリソースは解放されます。
百合子 さんが書きました: 追伸:
pthread_create(...)を使って実行される関数の間まったく順番関係がないでしょうか。
例えば、先にpthread_create(...)で実行された関数は後にpthread_create(...)で実行された関数より後に実行される可能性もありますか。
あります。
百合子 さんが書きました: C言語のpthread_create(...)を使って、threadをがんがん作成していきたいですが、
スレッドの生成、スケジューリング、切り替え(コンテキストスイッチ)には、オーバーヘッド(対象の処理を実施するために費やされる間接的な処理時間)が伴います。
また、スレッド毎にメモリが割り当てられている(場所が取られている)ことも忘れないでください。
生成しすぎると、結果的にパフォーマンスの劣化を招きます。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 15:29
by あんどーなつ
Linuxのスレッド数上限に関しては、情報があるみたいです。
http://www.yunabe.jp/docs/maximum_numbe ... reads.html

Windowsのpthread実装は、pthread-win32というオープンソースがあるようですが、あまりメジャーではないようです。
百合子さんがすでにUNIXプログラミングに精通しているならば、使う意味がありますが、そうでなければ使わないことをお勧めします。Visual StudioでCLAPACKを動かそうとして苦労していた人もいたみたいですので。

Windowsでマルチスレッドをするのであれば、下記のものがおすすめです。この掲示板で質問してもすぐ答えが返ってくると思います。
.NET Framework -> BackgroundWorkerクラス
Windows SDK -> CreateThread関数

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 21:14
by hide
オフトピック
横からですみませんが、なぜ.NetではBackgroundWorkerを押しているのか理由を聞いてもいいですか?
個人的には多少の何かしらの犠牲があったとしてもasync/awaitを使ったTaskのほうが読みやすくて良いと思ってます。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 22:50
by あんどーなつ
async/awaitは使ったことがないんです。すみません。
個人的には、ラムダ式のような見た目が初心者向けではないかなと思います。
Threadクラスが一番単純なのですが、fork/joinを思わせる仕組みがなんとなく好きじゃないです。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月11日(金) 23:10
by YuO
オフトピック
あんどーなつ さんが書きました:async/awaitは使ったことがないんです。すみません。
個人的には、ラムダ式のような見た目が初心者向けではないかなと思います。
ラムダ式……?Taskを直接使っている場合にはラムダ式で書くことも多いですが……。
see) http://dixq.net/forum/blog.php?u=546&b=3452
まぁ,async/awaitはConfigureAwait(false)忘れてUIの資源使ってしまったり,ADO.NETのドライバーが実はasync/await対応していなくてawaitをUIスレッドを止めてしまったり,という罠はありますが……。
あんどーなつ さんが書きました:Threadクラスが一番単純なのですが、fork/joinを思わせる仕組みがなんとなく好きじゃないです。
Threadクラスなんて,COMのApratmentの指定が必要な時以外,.NET 1.0時代から不要です。
.NET Frameworkでのスレッドの推奨は,.NET 1.0時代より一貫してスレッドプールを利用することです。
で,オフトピからメインのトピックの話に強引に戻して……。
百合子 さんが書きました:C言語のpthread_create(...)を使って、threadをがんがん作成していきたいですが、
スレッドを大量に作ることは,既にsleepさんが指摘されているとおりリソースを馬鹿食いするだけで遅くなります。
論理コア数と同数のスレッドが実行されている時が一番効率がよいとよく言われますが,実際問題として現在のOSはマルチプロセスであるため,他のプロセスの利用具合によって最大効率が得られるスレッド数は変化します。
ただ,アプリケーションとしては論理コア数と同数までスレッドプールのスレッドを実行するような実装が多いようです。

先に書いてしまいましたが,大量にスレッドを作る場合は,最低でもスレッドプールの利用を考える方が良いです。
pthreadやC++のthreadにはスレッドプールが用意されていないようですので,各種ライブラリを使うなどをするのがよいでしょう。
Windowsでは,CreateThreadPool APIをはじめとする,Thread Pool API群を使うとよいかと思います。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月12日(土) 08:53
by あんどーなつ
hide さん
YuO さん

私のコメントについてご指摘ありがとうございます。非常に参考になります。ちなみになんですけれども、非同期処理について下の2つの場合以外の使用例などありましたらご教授いただければ嬉しいです。

・時間のかかる処理(シミュレーション、レンダリング等)のスループットを上げる
・多少時間のかかる処理(ファイルロード、デバイス待ち等)を行うときにGUIが止まらないようにする

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月12日(土) 19:18
by BSS
横からすみません。

百合子 さんが書きました:
Q2: 生成したthreadは解放を(消滅させ)したりする必要はないでしょうか。

この質問に対して
sleepさんが書きました:
生成したスレッドに実行させていた関数が終了すれば、割り当てられていたリソースは解放されます。
=====================
ところが、下記のlinkに
「pthread_createで作ったスレッドはdetachしない限りはjoinしないとスタックなどのリソースが 解放されない。
従ってjoinするのを忘れるとメモリリークを起こす。」
言う出張が出されて、実証されました。
http://www.hakodate-ct.ac.jp/~tokai/tok ... etc/p4.htm
<pthread_createしたらjoinを忘れない>

=====================
ご説明できる方いらっしゃいませんか。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月12日(土) 21:17
by sleep
BSS さんが書きました:横からすみません。

百合子 さんが書きました:
Q2: 生成したthreadは解放を(消滅させ)したりする必要はないでしょうか。

この質問に対して
sleepさんが書きました:
生成したスレッドに実行させていた関数が終了すれば、割り当てられていたリソースは解放されます。
=====================
ところが、下記のlinkに
「pthread_createで作ったスレッドはdetachしない限りはjoinしないとスタックなどのリソースが 解放されない。
従ってjoinするのを忘れるとメモリリークを起こす。」
言う出張が出されて、実証されました。
http://www.hakodate-ct.ac.jp/~tokai/tok ... etc/p4.htm
<pthread_createしたらjoinを忘れない>

=====================
ご説明できる方いらっしゃいませんか。
pthread_create関数でスレッドを作成する際の detach state属性の規定値が PTHREAD_CREATE_JOINABLE だからです。
規定値で作成した場合、joinされることが想定されています。
joinの役目はスレッドの終了を待つことです。もし、PTHREAD_CREATE_JOINABLE で作成された、スレッドの状態を保持するリソースが先に解放されてしまっていると pthread_join関数でスレッドの終了を判定することはできなかったことでしょう。

PTHREAD_CREATE_DETACHED を指定してスレッドを作成することもできます。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月14日(月) 09:56
by 百合子
みなさん
ご指導ありがとうございます。
大変勉強になりました。
ご提示いただいた幾つかのリンク先も非常に素晴らしい文章です。

やはりthreadを多量発行するには thread poolを利用するのは常識みたいですね。
windowsが提供しているthread poolのAPIは悪くないが、将来LINUXに移植する可能性もありますので、
ちょっと欲張りな要望ですみませんが、
ソースコードのレベルで見かけ上LINUXでもwindowでも同じようなやり方はないでしょうか。

またどうぞ宜しくお願いします。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月14日(月) 11:20
by あんどーなつ
マルチスレッドに関しては、Javaに定評があります。
.netもLinuxに対応してきているみたいです。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月15日(火) 13:11
by 百合子
お返答ありがとうございます。

// Javaに定評があります
すみません、
C/C++言語に限定しての話ですけれども。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月15日(火) 18:11
by あんどーなつ
百合子 さん

すみませんでした。C++でプラットフォーム非依存となるとQtが思いつきます。商用版とGPL版があります。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月16日(水) 11:35
by YuO
百合子 さんが書きました:やはりthreadを多量発行するには thread poolを利用するのは常識みたいですね。
windowsが提供しているthread poolのAPIは悪くないが、将来LINUXに移植する可能性もありますので、
ちょっと欲張りな要望ですみませんが、
ソースコードのレベルで見かけ上LINUXでもwindowでも同じようなやり方はないでしょうか。
先にも書きましたが,現時点では標準機能としてthread poolは存在しないので,真似るしか無いようです。
実際に実装した事が無いので検索してみましたが,Boost.Asioを使って実装する,<thread>を駆使する,などが見つかりました。

ただし,Windows APIではないものの.NET Frameworkのスレッドプールはufcpp氏の記事にあるような,ローカルキューとグローバルキューからなる構成のようです。
Windows ThreadPool APIがこのようになっているかは不明ですが,それなりに色々なことが考慮されていると思われます。

このため,インターフェースだけ共通にしててしまって,
  • Windows環境ではWindows ThreadPool APIを呼び出す
  • Linux環境ではPOSIX Thread APIやBoost.Asioで模倣する
といった方法もありかと思います。
オフトピック
Boost.Asioや<thread>を使う場合では,論理コア数の取得がやはり標準的な方法でできないため,最大スレッド数を決められない,という問題が残ります。
このため,実装分離はスレッド数をコア数までに制限しようとした場合にも有効にな方法です。

Re: C言語のpthread_create(...)関数の使い放題

Posted: 2016年11月25日(金) 10:15
by 百合子
皆様
よく分かりました。
いろいろ教えていただきまして、本当にありがとうございました。