• 締切済み

プログラムのマルチスレッド化について。

マルチスレッド化したプログラムの作成を行いたいと思い、 前に作った、スライス画像を作成するプログラムを マルチスレッド化しようと、自分作ってみたのですが、デバック中に エラーで、止まってしまいます。 プログラムはこれです。http://koushi12.if.land.to/main.h この中の、///ここでエラーがでます/// というところで止まってしまいます。 ちょっと長いので、もしお時間ある方いらっしゃっいましたら見ていただき、修正箇所を指摘していただきたいのですが、 プログラム読むほど時間無い方には、質問で答えて頂きたいのですが、 各スレッドに、データ(引数)を渡すところで、 1つのデータ(例えばポインタで作ってある、画像データ)を、2つのスレッドに渡しても大丈夫なのでしょうか? データは、2つ作って、それぞれを、それぞれのスレッドに渡さないとダメなのでしょうか? それと、例えば、出力関数などを1つだけ作ってあったとして、 それを、各スレッドの中で、呼び出して大丈夫でしょうか? 関数も、各スレッドが呼び出しで衝突しないように、2つ作る必要があるのでしょうか? すみませんが、回答よろしくお願いします。

  • pen123
  • お礼率58% (222/377)

みんなの回答

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

ざっとソースを見ました。 かなり突っ込みどころ満載です。 ・エラーの原因。 DATA *data1, *data2;//マルチスレッド用 mallocしてますが値を入れていませんので、この構造体の値は不定です。スレッドが値を参照してちゃんと動くはずがありません。デバッガですぐ分かるはずなので、デバッガのちゃんとした使い方を理解してください。 特にスレッドプログラミングするためには、ちゃんとデバッガを使えるようになっていないとダメです。 ・mallocを使いすぎ。サイズ固定でスタックを大量消費しないならローカル変数で十分。freeを忘れてる変数がありますよ。 mallocは、サイズが可変する場合だけ使いましょう。 ・同じ処理をするのにスレッドのソースコードを分ける必要はありません。 ・2つのスレッドから同時にprintfすると混ざり合ったりして意味不明になります。状況表示したいならプロセス間通信などを使ってメイン側で状況を表示してやりましょう。 ・2つのスレッドから同じファイルに同時open出来るはずがありません。 ・オープンエラーをチェックしていません。 ・今回の処理は、同じデータを2つのスレッドで同時に処理しているだけに見えます。コンパイラやOSがうまく処理してくると思ったら大きな間違いですので、ちゃんと自分で面倒を見ましょう。 総じてスレッド以前にC言語の勉強不足です。知識不足から行ったスレッドの動作設計はスレッドの体をなしていません。 スレッド化する場合の注意点は、 ・入出力(ファイルとメモリ)をスレッド毎に分離すること。 ・CPU使用率100%なスレッドを作って効果があるには、マルチコアなCPUだけです。つまり、速度アップ出来るかは環境しだいです。CPU使用率が低い場合にはどんな環境でもスレッド化である程度の速度アップが期待できます。 ・スレッドセーフとい概念を理解している必要があります。つまり、OSのファイル管理やメモリ管理、プロセス管理をある程度以上理解している必要があります。

  • venzou
  • ベストアンサー率71% (311/435)
回答No.2

>1つのデータ(例えばポインタで作ってある、画像データ)を、2つのスレッドに渡しても大丈夫なのでしょうか? この場合、排他制御が必要になるでしょう。 下記のサイトの「4. 簡単な排他制御プログラム」などを参考にして下さい。 http://www.katto.comm.waseda.ac.jp/~katto/Class/GazoTokuron/code/thread.html >それと、例えば、出力関数などを1つだけ作ってあったとして、 >それを、各スレッドの中で、呼び出して大丈夫でしょうか? スレッドから関数を呼ぶ場合、その関数が「スレッドセーフ」である必要があります。 スレッドセーフでなければ、排他制御が必要です。 (出力関数であれば、おそらくスレッドセーフではないでしょう。) 「スレッドセーフ」については下記など参考にして下さい。 http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%82%BB%E3%83%BC%E3%83%95 #ソースは読んでません。 #自分が管理しているサイトへのリンクはルール違反ですよ。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

マルチスレッド化するのでしたらデータの分担を考えましょう 2分割なら元データを半分ごと分担するようにします 共通で使う資源があるならクリティカルセクションやミューテックスなどで同期を考えないといけないでしょう スレッド本体は同じ処理なら1つで良いと思いますよ 与えるポインタ引数に どこからどこまでのデータを扱うかといった情報を埋め込みましょう エラーが出るならその内容を具体的に記載しましょう

関連するQ&A

  • マルチスレッド化。

    今とても大きな配列を使用し、長時間処理をするプログラムを組んでいます。元々処理時間に1時間を要するプログラムを2分で処理を完了するまでに仕上げました。 しかし、探究心はおさまらずもう少し高速化に挑みたいと考えています。 過去に「猫でもわかる」のSDK第1章と2章を学び、マルチスレッドのプログラムをSDKで組んだことがあります。それを利用してマルチスレッド化を実現したいと考えています。 言語はCでVisualStudio2005を使用しています。 *疑問1   SDKの場合WinMain関数とプロシージャからの実行で_beginthread関数を記述すれば処理が開始されます。 Cでもmain関数内に記述すれば、SDKと同様に処理できるのでしょうか? *疑問2 _beginthread関数の引数に関してです。 第1引数にvoid型のスレッド関数、第2引数に0?、そして第3引数にはスレッド関数に渡すデータの引数を記述すると把握しているのですが、渡したいデータは複数あり、***型と**型、それに変数を数個とスレッド関数に渡したいデータだらけなのですが、どのように記述すればよいでしょう? *疑問3 2つのスレッドを作成しようと考えていますが、その2つのスレッドで1つの大きな配列を共有して処理したいと考えています。 そのため、スレッド間の同期が必要になるわけですが同期の種類にもクリティカルセクションやミューテックス、イベントと豊富でどれを使用すれば良いのか迷ってしまいます。厳密に同期を取り処理をするにはイベントが一番良いと考えています。 これらの疑問に答えられる方はアドバイスをよろしくお願いします。

  • マルチスレッドについて

    現在”猫でもできる”の87、88章を学んでおります。 まず87章でマルチスレッドの根本的なやり方を学びましたが、いきなり疑問が浮かびました。 _beginthread関数によりスレッドをスタートさせ、この関数で登録した関数内で_endthread関数を実行し終了させていることは分かります。 しかし_beginthread関数で登録した関数に引数を渡す処理がどの部分で行われているのかわかりません。 登録する関数はvoid型で引数はvoid*型でなければいけないことは分かったのですが、プログラムのどこを見てもこの登録した関数に引数を渡す処理が行われていません。 その辺の動作の説明を分かる方でいいのでよろしくお願いします。 そして88章では排他制御のマルチスレッドを行うプログラムの製作を行っているのですが、ちょっとした疑問が浮かびました。 EnterCriticalSection関数、LeaveCriticalSection関数ではさまれたプログラムは排他制御され他からアクセスされない。 この関数はこんな理解で良いんですかね? この理解で行くと、88章で説明していきますが、子ウィンドウを2つ作成しそれぞれのプロシージャ内で排他制御された関数をスレッドとしてスタートしています。 この2つのスレッドの動作についてですが、互いに排他制御関数が記述されているため、動作としてはまず左の子ウィンドウのスレッドが処理されている場合、右の子ウィンドウのスレッドは停止している。そして左の子ウィンドウのスレッドの排他制御が解放されたときに、右の子ウィンドウのスレッドが開始する。 そしてあるとき左の子ウィンドウのクライアントウィンドウ内で右クリックされた場合、その時点で排他制御されたスレッドが終了するのを待ち、終了したらcountを+1する。 こんな動作が行なわれていると理解してよいのでしょうか?

  • (マルチスレッド)_beginthreadexに複数の引数を渡す

    現在プログラムでマルチスレッドをやろうとしているのですが、 マルチスレッドの関数に数値や配列などの引数を渡すことは可能でしょうか? MSDNで調べてみると、_beginthreadex関数の4番目のNULLのところに引数リストを 指定できるとあったのですが、その意味が良くわかりませんでした。 以下のプログラムの場合にマルチスレッドに変数a, b, cを引数として渡したい場合は どのように書けばいいのでしょうか? #include <stdio.h> #include <windows.h> #include <process.h> unsigned WINAPI MyThread( void *lpx ){ while (1) { printf("スレッド実行中\n"); Sleep(1000); } return 0; } void main(){ // スレッドに渡したい変数の宣言 int a = 128; int b = 256; int c = 512; // スレッドIDの宣言 DWORD thID; // マルチスレッドの開始 (HANDLE)_beginthreadex( NULL, 0, &MyThread, NULL, 0, (unsigned int*)&thID ); // ループ while (1) { printf("メイン関数実行中\n"); Sleep(2000); } }

  • メインスレッドのPostMessageとマルチスレッドでの処理

    お世話になります、fujicafeと申します。 現在Visual Studio 2005にてVC++のプログラムの作成をしており、 お聞きしたいことがありまして、こちらにて投稿させていただきました。 質問したい内容はPostMessageによる非同期呼び出しによるメインスレッド関数の処理と、別スレッドからのメインスレッド関数呼び出しによる処理の違いについてです。 現在、メインスレッドにマルチメディアタイマーを使って、ある時間間隔毎にメインスレッドの関数を呼び出しています。その関数の呼び出しにはPostMessageを使用しています。 その関数の呼び出しをAfxBeginThreadを使用して、メインスレッドから別スレッドを作成し、その別スレッド内にてメインスレッドのオブジェクトを作成して、実行したいメインスレッドの関数を呼び出すと、もともとのPostMessageを使用して関数を呼び出すのとでは処理としてどのような違いがあるのでしょうか? スレッドを別にするということで、メインスレッド側に負荷をかけないといったことが違うのでしょうか? だいぶ検討はずれの質問かとは思いますが、ご教授よろしくお願いいたします。

  • メンバ関数(メソッド)をマルチスレッドにしたい

    環境はWinXPでVisual Studio 2005を使用しています。 C言語で関数をマルチスレッド化するにはこんな感じでOKでした。 // マルチスレッド関数 void Thread( void * ) { } void MainFunc() {   (HANDLE)_beginthread( Thread, 0, NULL ); } こんな風にスレッド関数をC++のメソッドに変えてうまくいくかと思い class Test_c { public:   void Thread( void * ); } ; // マルチスレッド関数 void Test_c::Thread( void * ) { } void MainFunc() {   Test_c t t;   (HANDLE)_beginthread( t.Thread, 0, NULL ); } とするとエラーが出てきてしまい、コンパイルが通りませんでした。 C++のメンバ関数をマルチスレッド関数としたい場合はどの様に書けばよいのでしょうか・・?

  • マルチスレッド

    ウインドウズプログラミングを始めて1ヶ月弱の初心者です。 色々探してみたのですが、結局良く分かりませんでした。 宜しくお願いします。 以下のリンクにおいて、 http://wisdom.sakura.ne.jp/system/winapi/win32/win143.html 1)主スレッドとは、具体的にソースファイルのどこからどこまでのことを言うのでしょうか? そもそもスレッドとは何でしょうか?関数のことでしょうか? また、タスクとは、実行ファイルと考えて良いのでしょうか? 2)副スレッド(ThreadFunc)を作成すると、主スレッド(WinMain?)と副スレッドで並列処理をするとのことですが、CPUは普通一つしかないので、実際は、主スレッド(WinMain?)と副スレッドを常に切り替えながら動作すると思います。が、ここで疑問なのですが、主スレッドと副スレッドの切り替えはいつ誰が行うのでしょうか?また、切り替えタイミング(例えば1ms毎に切り替えたいとか)は自由に設定出来るのでしょうか? 3)"マルチスレッドは親プロセスのメモリ空間を共有します" とあるのですが、これは CreateThread(NULL , 0 , ThreadFunc , (LPVOID)hWnd , 0 , &dwID) の(LPVOID)hWnd を、副スレッド(ThreadFunc)に引数として渡しているから、つまり、主スレッドと副スレッドは、(LPVOID)hWnd だけがメモリを共有する、ということでしょうか? 主スレッドと副スレッドでメモリを共有すると、どんなメリットがあるのでしょうか? 4)マルチスレッドはこういう時に使うとよい、 というような大まかな判断基準があれば教えて下さい。 分かり辛い質問で申し訳有りません。宜しくお願い致します。

  • スレッド内でのマルチスレッドの作成[WINDOWSプログラミング]

    いつもお世話になっております。 現在WINDOWSプログラムでゲームを最中なのですが、スレッド内でスレッドを作成できなくて困っています。 キャラを動かすスレッドで以下の関数を使い、スレッドを作成しようとしたのですが、 CreateThread(NULL, 0, ATK, (LPVOID)&x, 0, &dwID); 以下のようなエラーメッセージが出てしまいます。 'ATK':定義されていない識別子です '関数' : 間接参照のレベルが 'LPTHREAD_START_ROUTINE' と 'int' で異なっています。 'CreateThread' : の型が 3 の仮引数および実引数と異なります。 わかる方いましたらどうがご指導お願いします。 初歩的なミスでしたらすみません。

  • マルチスレッドについて。

    今、大きな配列を元に処理を行うプログラムを作成しています。 シングルスレッドでも十分速度を向上するようチューニングに成功しましたが、マルチスレッド化をすればさらに速度を向上させることができるだろうと考え、先日マルチスレッドかに成功しました。 しかし・・・奇妙な現象が起こりました。 マルチスレッドで性能を引き出すには、排他制御はないほうが良いと考え、メモリは食いますがスレッドに与える入力情報(大きな配列)を2つ用意し、排他制御なしの2スレッドを実行できるようにしました。しかしやはりメモリを消費しすぎてしまうため、配列にアクセスする部分のみ排他制御を行うようクリティカルセクションを設定し入力情報を2スレッドで共有して処理を行うよう組み替えました。 結果、やはり排他制御なしの場合よりはるかにスピードダウンしてしまい、シングルスレッドより少し早い処理時間で終了してしまいました。 余りにも悔しいため、ちょっと危険な実験だとは思いましたが、入力情報を2つのスレッドで共有しているにもかかわらず、排他制御の部分、つまりクリティカルセクションを取り除いて実行してみようと考えました。予想としては同時にアクセスし衝突が起きてエラーで停止してしまうと考えましたが・・・・・・ 結果なぜかエラーなく処理をし続け、普通に終了してしまいました。 これはなぜでしょう? 偶然にも共有情報に同時にアクセスすることがなかったためでしょうか?

  • マルチスレッドに挑戦したい

    <プログラム環境> Windows XP VC++6.0 MFC AppWizard(exe) ダイアログベース <目的> COMポートでバイナリデータの送受信を行う <プログラムの仕様> 1.ダイアログの「受信開始」ボタンを押す    データ受信開始の合図"0x01"を相手機器に送る 2.相手機器がデータを永遠と送信してくる 3.データを永遠と受信する 4.ダイアログの「受信終了」ボタンを押す    データ受信終了の合図"0x02"を相手機器に送る 5.相手機器がデータ送信を止める 6.受信終了 <質問> 上記のプログラム仕様を満たすには、マルチスレッドにしないといけないと思うのですが(データの送信と受信でスレッドを分ける)、具体的に何をどうすればマルチスレッドになるのか分かりません。 マルチスレッドに必要な関数、 プログラムの全体的な流れなど、 基本的な部分を教えてください。 宜しくお願いします。

  • MFCマルチスレッドについて

    MFCマルチスレッドについて COMやIOボードからの入力に応じて動作するアプリを作っています。 AfxBeginThreadにてそれぞれワーカスレッドを作成しCOMやIOから入力があれば AfxBeginThreadを呼んでいるクラスにあるメンバ関数を実行しようとしています。 AfxBeginThreadにて*thisを送り、制御関数内で、mycls->OnButton***()というような 感じで現在は作っています。(OnButton***になっているのはデバッグ用にボタンで あらかじめ作成している関数のためです。) このときに、mycls->OnButton***()は親スレッドで動いていると考えていいのですか? あくまで親スレッドのクラスのメンバ関数を制御関数が動いている子スレッドで実行 しているだけなのでしょうか? 実は、ログ表示のため制御関数の中(受信データを表示)と、mycls->OnButton***()の中 (作業結果を表示)に同じエディットコントロールへの表示部分があります。 表示部分の処理は、いったんCStringで読み込んできて最大文字数チェックを行い、 再度文字数を調節して書き直しということをやっているため、一応クリティカル セクションにはしているのですが、実際どう動いているか分からないため、やり忘れ ていることや、やってはいけないことをやってそうです。 すいませんがご教授願います。

専門家に質問してみよう