質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

89.98%

C言語で処理のスケジューリング

受付中

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 2,420
退会済みユーザー

退会済みユーザー

C言語のプログラムを書いています.
現在ネットワークのソケット通信部分をマルチスレッドの形にしてプログラムを書いているのですがサーバプログラム側の性能(実装方法?)の問題で処理の待ち受けが発生してしまっています.
そのためマルチスレッディングで同時アクセスすることをやめ, スケジューリングを行い, 一定期間で処理を連続して行おうということを考えました.
ただし処理時間の制約が非常に強く, 例えばマルチスレッディングをやめてシーケンシャルにアクセス...といった実装はできないです.

どのような解決方法があるでしょうか?
現在はこちらから送るリクエスト数の合計は5000くらいを想定していて, 同時にスレッドを作成し, 通信していますが
だいたいサーバ側で処理の待ち受けが発生するのは同時アクセス数150あたりからのようです.
考えたのは150アクセスごとに分け, スケジューリングをして適切な感覚で送信することなのですが実装方法がいまいちわかりません.
よろしくお願いいたします.

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kozuchi

    2015/12/25 17:42

    以下の点について追記したほうがよい回答をもらえると思います。

    ・プロトコルは何を使っていますか?
    ・開発対象にサーバは含まれますか(サーバ側での対応は考慮に含めていいですか?)
    ・サーバ(アクセス対象)は一つですか(Webサーバであれば複数サイトですか、一つのサイトですか?)
    ・サーバ側はどのような構成を想定していますか?(負荷分散などはどうしている前提ですか?)
    ・何のためにマルチスレッド化するのですか?(マルチスレッド化で期待する効果はなんですか?)

    ※また、C言語とマルチスレッドを使ってらっしゃいますが、
    どちらかというとネットワークプログラミングの問題ですので、
    タグには「ネットワーク」と、
    使用可能なタグに使っているプロトコルタグにあれば
    そのプロトコルのタグ(「HTTP」「FTP」など)を指定することをお勧めします。

    キャンセル

回答 4

+1

「処理時間の制約が非常に強く・・・」とありますので、例えばハードウェア割り込み処理(短時間で処理を完了してCPUを開放する必要がある)の中で、サーバーへのデータ送信を実行しようとしているが、サーバー側のレスポンスが遅くて完了待ちが発生してしまう、というような状況だと仮定します。

この場合、定番のデザインパターンとして、「送信キュー」という仕組みを作ります。割り込み処理の中ではリクエストメッセージを作成してそれをキューに入れ、ただちに処理を完了させるようにします。そうしておいて、このキューからリクエストメッセージを取り出してサーバーに送信する処理を別スレッドで走らせます。もしサーバーへ送るリクエストの順番を維持したい場合はスレッド数を増やす、リクエストの順番に意味がないのであれば、キューとスレッドをセットで増やすなどの方法で、パフォーマンスを最適化することができます。

「キュー」とは何かということについては、「キューとスタック」などで検索すると多数ヒットします。簡単に言うと、同時多発的に発生するデータを一列に整列させ、FIFO(First in First out/先に列にならんだものを先に)処理するための仕組みです。単純なキューは、構造体やクラスインスタンスの実体かポインタの配列として実装されます。ただし配列要素数が数千や数万の単位で可変長になる場合には、単方向/双方向のオブジェクト参照リストとして実装するほうがパフォーマンス的に有利にできると思います。

クライアント/サーバーシステムで「送信キュー」や(今回は不要ですが)「受信キュー」などの仕組みを使うパターンについては、「メッセージキュー」や「疎結合分散システム」などで検索するとより詳しい情報を得ることができると思います。

ご参考になれば。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

セマフォを使って同時リクエスト数を100くらいに制限しては如何でしょうか?
セマフォの内カウンティングセマフォと呼ばれるものが使えると思います。

Windowsならこの辺が参考になると思います。
その他のOSについては私は分かりませんが、linuxもありそうです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

あらかじめスレッドを作成しておいて,親スレッドはリクエストが来たら空いている子スレッドに処理を投げるだけ,子スレッドは受け取ったリクエストをさばく,という実装になっているのでしょうか?

スレッド数を増やせば,空いている子スレッドが無いために親がリクエストを保留するという待ちは減らせるかもしれませんが,同時に実行できるスレッド数にはCPUに依存する限界がありますから,子スレッドがリクエストをさばくためにCPUのスケジューリング待ちをする時間はどうしても存在します.
OSの機能を使って作ったスレッドであればOSのスケジューラに依存しますし,ユーザレベルのスレッド機能を使って作ったスレッドであればそのライブラリか何かのスケジューラに依存します.
一般ユーザレベルスレッドの方が高速に切り替えられると言われているので,互換性は犠牲になりますが,スループットを向上させるためには良いかもしれません.

逆に,子スレッドの空きは十分にあるのに,親スレッドのリクエストのさばき方が悪いために遅くなる場合もあります.
どのような関数でリクエストの到来を待っているのかによって,同時接続数の上限も変動する可能性があります.(Linuxであればselect,poll,epollなどたくさんあります)

まずは,どこがサーバプログラムのボトルネックになっているのかの調査が必要だと思います.
また単一のサーバプログラムで処理をすべて行うためには,上述のような限界もありますので,ロードバランサの導入も検討してみてください.
(「150アクセスごとに分け, スケジューリング」というのはロードバランサのことでしょうか?)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

一般的な話になってしまいますが、送受信処理をうまく回すためには、送受信スレッドは1つずつにするのが普通です。つまり、送受信の交通整理を専門で行うスレッドを用意するわけです。送信スレッドは送信に専念し、受信スレッドは受信に専念するわけです。
ハンドシェーク要求を持っているスレッドはそれとは別に(1つないし複数)作成しておき、各ハンドシェークスレッドは送信スレッドにキューなどを使って送信要求を出します。送信スレッドはキューを監視しておいて、データが有ればサーバーにデータを送ります。
受信スレッドは、受信データがあれば各ハンドシェークスレッドに受信データを返します。ただ、ハンドシェークスレッドが複数ある場合は、受信データからどのハンドシェークスレッドに返したらいいのか区別できるようにしておかなければいけません。その辺はデータの内容によって分けることになるのでハンドシェークスレッドの別け方をどうするかということになります。
こうすれば、時間待ち(監視)は各ハンドシェークスレッド個々で行えばいいことになります。各ハンドシェイクスレッドの送信周期も各スレッド毎に制御します。

後は待受が発生したことをどう認識するかですが、サーバー側の話なので基本的には難しいと思います。サーバーに送信するアプリが1つしか無いのであれば送受信数で判断つきますが、サーバーには複数のアプリから要求が来るでしょうから、それを各クライアントが判断するのは基本的には難しく、レスポンス時間で判断するするしか無いように思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる