server0 は送信源(率 \(1/25\) でパケットを生成)。server1..5 がルータで、それぞれ固有の平均サービス時間 t_ave とバッファサイズ q_max を持つ。
下のテキストエリアには 配布/sample3.cpp の中身がそのまま貼り付けてある。// *** の箇所を埋めて、
「sample3.cpp をダウンロード」で自分の環境に保存できる。
配布/sample3.cpp)の // *** を埋める:
server::service の dist==3(指数): sample2 と同じロジックmain() の server1..5 の 3 つ目の引数(平均サービス時間 t_ave)と
4 つ目の引数(バッファ数 q_max)を決める5, 6, 10, 15, 18, 30(小さいほど高性能)、バッファ総数 \(= 20\)。
順序(どの性能を直列のどこに置くか)も自由。
g++ sample3.cpp && ./a.out最終行の
average rate がスループット。配置を変えて複数回実行し、最大値を探す。#define TRACE_QUEUE 1 にして 1 回実行すると queue_trace3.csv が出力される。
専用ツール (sample3_viewer.html) で読み込むと:
TRIAL:1 440129 400220 TRIAL:2 ... average rate = 0.0400502
各試行ごとに total_packet(全期間)と target_packet(BEGIN_TIME 以降のみ)を表示し、最後に平均スループット。
#define TRACE_QUEUE 1 にすると queue_trace3.csv(t, q1..q5, departed 列)が出力される。
sample3_viewer.html で読み込むと:
BEGIN_TIME | 測定開始時刻(例 1,000,000)。これ以前は過渡状態(空から満たされていく途中)なので統計対象外。 |
END_TIME | 測定終了時刻(例 11,000,000)。 |
TRIAL | 独立試行回数(例 5)。結果は平均される。 |
DIST_TYPE | サービス時間分布。3:指数(sample2 と同じ)。 |
各ルータにはバッファサイズ q_max があり、キュー長がそれを超えるパケットは入れない。
server::departure では next->arrive() を呼んで次のサーバに入れようとする:
void server::departure(double t_c){
t_current = t_c;
if(order == 5){ // 最終サーバ
total_packet++;
if(t_current > begin_time) target_packet++;
queue--;
...
}
else{
int result = next->arrive(t_current); // 次のルータに入れる試み
if(result == 1){
queue--; // 成功: 自分から 1 個減らす
...
}
else{ // 失敗(次が満杯): ブロック
t_finish = next->get_t_finish();
(*top)->add(this, t_finish);
}
}
}
次のサーバが満杯(arrive が 0 を返す)だと、自分のパケットは 動けない。
次のサーバの離脱時刻 t_finish を待って再試行するように、スケジューラに登録し直す。
t_ave が大きい)の手前が連鎖的に詰まる。
バッファが足りないと、さらに前のサーバもブロックされて系全体が停滞する。
server5 だけが総離脱数をカウントする。begin_time 以降にカウントされた target_packet を観測時間で割る:
TRIAL 回繰り返して平均を取り、average rate として出力する。
シミュレーション開始直後は全バッファが空で「まだ詰まっていない」状態なので、スループットが一時的に高く見える。
定常状態(各バッファが平均的にある程度埋まった状態)に達してから測定するため、BEGIN_TIME までは捨てる。
server::service の dist==3: 指数サービス時間 t_finish = t_c + (-t_ave)*log(1 - ran2(idum))(sample2 と同じ)main() の server1..5 の引数: t_ave(3つ目)と q_max(4つ目)を決める。合計 q_max = 20class server server1(1, dist, 6, 4, idum, &top, t_b); class server server2(2, dist, 10, 4, idum, &top, t_b); class server server3(3, dist, 15, 4, idum, &top, t_b); class server server4(4, dist, 20, 4, idum, &top, t_b); class server server5(5, dist, 5, 4, idum, &top, t_b);
上は既定の例(合計バッファ 20)。配置と値を変えて average rate が最大になる組み合わせを探す。
イベントドリブンと ran2() の仕組みは課題2と共通。詳しい解説は
課題2のページ 参照。