リアルタイム制御

ソフトリアルタイム

多少の遅れが許容される要件。

概要

ソフトリアルタイム(Soft Real-time)とは、処理のデッドライン(期限)を超過しても直ちに致命的な障害につながらず、品質の低下や一時的なサービス縮退に留まるリアルタイム要件のことです。

ハードリアルタイムとの最大の違いは、デッドライン超過の結果です。ハードリアルタイムではデッドラインを1回でも破ると致命的な損害(人命・機器損傷)をもたらしますが、ソフトリアルタイムでは遅延が発生しても「映像がコマ落ちする」「音声が少し途切れる」「操作への応答が遅れる」程度の影響で収まります。

リアルタイム性全体の分類では、ハードリアルタイムとソフトリアルタイムの中間に「ファームリアルタイム(Firm Real-time)」を置く場合もあります。ファームリアルタイムでは、デッドライン超過した結果は無価値として捨てるものの、致命的にはならない(例:金融の高頻度取引で遅延した注文を棄却する)要件を指します。

歴史・背景

ソフトリアルタイムという概念は、1990年代のマルチメディアコンピューティングの普及とともに重要性が増しました。音声・動画のデジタル処理では、一定の処理周期(例:30fps = 33.3ms周期)で映像フレームを生成する必要がありますが、フレームを1枚落としても放送設備が壊れるわけではなく、視聴品質が低下するだけです。

2000年代初頭、インターネット動画配信(YouTube、Netflix等)の登場により、ソフトリアルタイムの需要がさらに拡大。バッファリングやアダプティブビットレート(ABR)制御により、ネットワーク遅延の影響を吸収しながら映像を連続再生する技術が発展しました。

組み込み分野でも、組み込みLinuxの普及に伴い、Linux上でソフトリアルタイム処理を行う機会が増えました。標準のLinuxカーネルはスループット重視の設計であり、割り込みレイテンシが数ms〜数十msになる場合があります。そこで登場したのがPREEMPT_RTパッチで、カーネルのほぼすべての部分をプリエンプト可能にしてレイテンシを100μs以下に抑えることを目指しています。

技術仕様

ソフトリアルタイム性能の目安

用途許容レイテンシ典型的なジッタ上限
動画再生(30fps)〜33ms±10ms
音声処理(48kHz)〜10ms(バッファ含む)±1ms
ゲーム(60fps)〜16.7ms±5ms
タッチ操作応答〜100ms±20ms
Webページ描画〜100ms(体感)制限なし
リモートデスクトップ〜200ms(視覚許容)±50ms

Linuxカーネルのプリエンプションモード

標準Linuxには以下のプリエンプション設定があります。

設定説明最悪レイテンシ
No Forced Preemptionサーバ向け・スループット最大化数十ms
Voluntary Kernel Preemptionバランス型(デスクトップ向け)数ms〜数十ms
Preemptible Kernel低レイテンシ(組み込みLinux)数ms
PREEMPT_RT(Full RT)ほぼすべてプリエンプト可100μs〜1ms

PREEMPT_RTはLinux 6.12以降でメインラインに統合されています。

PID制御との組み合わせ

ソフトリアルタイムでPID制御を行う場合、制御周期の変動(ジッタ)がPIDパラメータに影響します。可変周期に対応した離散化手法(後退差分法)を使うか、高精度タイマで周期を安定させる必要があります。

/* 可変Δtに対応したPID(組み込みLinux向け) */
double pid_update(PID *pid, double error, double dt) {
    pid->integral += error * dt;
    double derivative = (error - pid->prev_error) / dt;
    pid->prev_error = error;
    return pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative;
}

動作原理

タイムバジェットとQoS

ソフトリアルタイムシステムでは、デッドラインを絶対保証するのではなく、一定比率(例:95%以上のフレームを33ms以内に処理)を目標とする品質指標(QoS: Quality of Service)で要件を表現することが多いです。

QoS指標の例:
・P99レイテンシ 50ms以下(99パーセンタイル)
・フレームドロップ率 1%以下
・バッファアンダーラン発生回数 1時間に5回以下

Linux上でのリアルタイムスレッド

Linuxでソフトリアルタイム処理を実現するには、SCHED_FIFOまたはSCHED_RRスケジューリングポリシーと、適切な優先度設定が有効です。

#include <sched.h>
#include <pthread.h>

void setup_realtime_thread(pthread_t thread, int priority) {
    struct sched_param param;
    param.sched_priority = priority; /* 1〜99(高いほど優先) */

    /* リアルタイムスケジューリングポリシーを設定 */
    int ret = pthread_setschedparam(thread, SCHED_FIFO, &param);
    if (ret != 0) {
        perror("pthread_setschedparam");
    }
}

void *audio_thread(void *arg) {
    /* メモリをロックしてページフォルトを防止 */
    mlockall(MCL_CURRENT | MCL_FUTURE);

    struct timespec next;
    clock_gettime(CLOCK_MONOTONIC, &next);

    while (running) {
        /* オーディオバッファ処理(〜5ms以内) */
        process_audio_buffer();

        /* 次の処理タイミングまでスリープ(10ms周期) */
        next.tv_nsec += 10 * 1000 * 1000; /* 10ms */
        if (next.tv_nsec >= 1000000000L) {
            next.tv_sec++;
            next.tv_nsec -= 1000000000L;
        }
        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
    }
    return NULL;
}

レイテンシ隠蔽のバッファリング

音声・動画処理では、バッファ(リングバッファ)を用いてレイテンシの変動を吸収します。バッファサイズはレイテンシとロバスト性のトレードオフです。

バッファサイズ = 許容レイテンシ × サンプリングレート
例:20ms × 48000Hz = 960サンプル(44.1kHzでは882サンプル)

用途・ユースケース

マルチメディア処理

  • 動画エンコード/デコード: H.264、H.265のリアルタイムデコードは1フレーム(33ms)以内が目標。GPUハードウェアデコードを活用
  • 音声処理(DAW): プロ向けオーディオ編集ソフトは4〜10ms以下のバッファレイテンシを目標とし、JACK Audio Connection Kitなどのリアルタイム音声サーバを使用
  • ビデオ会議: WebRTCではジッタバッファで100〜500msの遅延を吸収しつつ映像・音声を同期

IoT・エッジコンピューティング

  • センサデータ集約: IoTゲートウェイでのセンサデータ受信・MQTT送信。数秒〜数十秒の遅延許容範囲が多い
  • エッジAI推論: TFLiteONNXによる物体検知。100ms〜1sの応答時間が許容される用途
  • 異常検知: 工場設備の振動・温度監視。数秒以内の検知でよい場合が多い

操作インターフェース

  • タッチパネル: 100ms以下の応答で快適な操作感(Fitt’s Law的にはUI応答は150ms以内が推奨)
  • ゲームコントローラ: 入力から画面反映まで50ms以下(遅延はゲーム体験に直結)
  • 産業用HMI: オペレータの操作への応答は200ms以下で十分なことが多い

実装・開発のポイント

CPU優先度とnice値

組み込みLinux環境では、ソフトリアルタイムタスクにnice値(-20〜19)やSCHED_FIFOを適用して優先度を調整します。ただしリアルタイム優先度(SCHED_FIFO/RR)を高く設定しすぎると、カーネルスレッドを飢餓状態にするリスクがあります。

# プロセスをリアルタイム優先度で起動
chrt -f 50 ./my_audio_process

# 実行中プロセスの優先度変更
chrt -f -p 50 <PID>

# nice値の設定(ソフトリアルタイム用途)
nice -n -10 ./my_process

ページフォルトの排除

Linuxでの割り込みレイテンシ増大の主因はページフォルトです。リアルタイムスレッドはmlockall(MCL_CURRENT | MCL_FUTURE)でメモリをロックし、スワップを防ぎます。

デバッグとプロファイリング

  • cyclictest: PREEMPT_RT環境でのレイテンシ計測ツール。最悪レイテンシ・ヒストグラムを取得できる
  • ftrace: Linuxカーネルの割り込みレイテンシ・スケジューリング遅延のトレース
  • perf: パフォーマンスプロファイリング(CPUサイクル、キャッシュミス等)
# cyclictest でレイテンシ計測(PREEMPT_RT環境)
cyclictest -l 100000 -m -n -p 80 -i 1000 -h 400
# -l: ループ回数, -m: mlockall, -n: clock_nanosleep,
# -p: 優先度, -i: 間隔(μs), -h: ヒストグラム最大値(μs)

他技術との比較

観点ハードリアルタイムソフトリアルタイム
デッドライン超過の影響致命的(安全障害)品質低下のみ
デッドライン保証100%(統計的でなく確定的)ベストエフォートまたは統計的
OS選択RTOS必須汎用OS(PREEMPT_RT Linux等)で可
動的メモリ原則禁止許容(ただしレイテンシに注意)
WCET解析必須任意(実測P99等で代替)
代表規格ISO 26262、DO-178Cなし(QoS要件で管理)
開発コスト非常に高い中程度

ソフトリアルタイムシステムは、ハードリアルタイムほど厳格な証明を必要としないため、豊富なソフトウェアエコシステムを持つ組み込みLinuxFreeRTOS上での実装が現実的です。要件に応じて適切な時間制約クラスを選択することが、コストと品質のバランスを最適化する鍵となります。

関連用語

参考リンク