2

Ubuntu 8.10でRDTSCを使用してコードの時間を計ろうとしています(私が試した他のプロファイリングソフトウェアは、必要な解像度まで時間を計ることができません)。しかし、タスクの切り替えや割り込みの発生から外れ値が発生し続け、統計が無効になっています。

私のプログラムが数ミリ秒で実行されることを考えると、私の環境ですべての割り込み (本質的にタスク スイッチをオフにする) を無効にすることは可能ですか? それとも、より強力な OS に移行する必要がありますか? 独自の OS カーネルを使用してこのタイミング コードを実行したほうがよいでしょうか? 私はアルゴリズムの最高/最悪のパフォーマンスを証明しようとしているので、タイミングが完全に安定している必要があります.

現在使用している関連コードは次のとおりです。

inline uint64_t rdtsc()
{
    uint64_t ret;
    asm volatile("rdtsc" : "=A" (ret));
    return ret;
}

void test(int readable_out, uint32_t start, uint32_t end, uint32_t (*fn)(uint32_t, uint32_t))
{
    int i;
    for(i = 0; i <= 100; i++)
    {
        uint64_t clock1 = rdtsc();
        uint32_t ans = fn(start, end);
        uint64_t clock2 = rdtsc();

        uint64_t diff = clock2 - clock1;

        if(readable_out)
            printf("[%3d]\t\t%u [%llu]\n", i, ans, diff);
        else
            printf("%llu\n", diff);
    }
}

このコードでオーバーフロー条件を適切に処理していないことに気付いた人への追加のポイント。この段階では、プログラムがタイムスライスを失ったために突然ジャンプすることなく、一貫した出力を得ようとしています。

私のプログラムの適切な値は -20 です。

要約すると、OS からの中断なしにこのコードを実行することは可能ですか? それとも、IRQ とスケジューリングを無効にできるように、リング 0 のベア ハードウェアで実行する必要がありますか? 前もって感謝します!

4

7 に答える 7

3

テストの各反復の直前に nanosleep() を呼び出して 1 秒程度スリープさせると、テストごとに「新鮮な」タイムスライスが得られるはずです。カーネルを 100HZ タイマー割り込みでコンパイルし、時間指定関数が 10ms 未満で完了する場合、タイマー割り込みがそのようにヒットするのを回避できるはずです。

他の割り込みを最小限に抑えるには、すべてのネットワーク デバイスの構成を解除し、スワップを使用せずにシステムを構成し、それ以外の場合は静止していることを確認します。

于 2009-08-01T03:25:18.797 に答える
2

トリッキー。オペレーティング システムを「オフ」にして厳密なスケジューリングを保証することはできないと思います。

これをひっくり返すと、非常に高速に実行されるため、何度も実行して結果の分布を収集します。標準の Ubuntu Linux が狭義のリアルタイム OS ではないことを考えると、すべての代替アルゴリズムは同じ設定で実行されます。そして、分布を比較できます (要約統計から分位数、qqplot まで、あらゆるものを使用します)。その比較は、Python、R、または Octave など、最も適したもので行うことができます。

于 2009-08-01T03:02:35.620 に答える
2

FreeDOSはシングル プロセス OS であるため、FreeDOSを実行することで問題を解決できる場合があります。

2番目のリンクからの関連テキストは次のとおりです。

x86 の世界における DOS システムの事実上の標準である Microsoft の DOS 実装は、シングルユーザー、シングルタスクのオペレーティング システムです。ハードウェアへの生のアクセスと、ファイル I/O などの OS API の最小限のレイヤーのみを提供します。組み込みシステムに関しては、これは良いことです。なぜなら、オペレーティング システムを邪魔することなく何かを成し遂げる必要があることが多いからです。

DOS には (ネイティブに) スレッドの概念がなく、複数の進行中のプロセスの概念もありません。アプリケーション ソフトウェアは、割り込みインターフェイスを使用してシステム コールを行い、さまざまなハードウェア割り込みを呼び出してビデオやオーディオなどを処理し、ソフトウェア割り込みを呼び出して、ディレクトリの読み取りやファイルの実行などのさまざまなことを処理します。

もちろん、エミュレーターではなく、実際のハードウェアで FreeDOS を実際に起動することで、おそらく最高のパフォーマンスが得られるでしょう。

私は実際にFreeDOS を使用したことはありませんが、あなたのプログラムは標準 C のように見えるので、FreeDOS 用の標準コンパイラが何であれ使用できると思います。

于 2009-08-01T03:09:16.063 に答える
2

プログラムがミリ秒単位で実行され、Linux で実行されている場合は、(Linux の) タイマー周波数が 100Hz (1000Hz ではない) に設定されていることを確認してください。(cd /usr/src/linux; menuconfig を作成し、"Processor type and features" -> "Timer frequency" を参照) この方法では、CPU が 10ms ごとに中断されます。

さらに、Linux のデフォルトの CPU タイム スライスは 100 ミリ秒であるため、nice レベルを -20 にすると、数ミリ秒実行してもスケジュールがずれることはありません。

また、fn() で 101 回ループしています。システムを適切に調整するために、fn() を no-op にすることを検討してください。

何度も印刷するのではなく、統計 (平均 + stddev) を作成します (スケジュールされたタイムスライスを消費し、端末は最終的にスケジュールなどを取得します... それを避けます)。

RDTSC ベンチマーク サンプル コード

于 2009-08-01T03:16:17.080 に答える
1

chrt -f 99 ./testを使用して、最大のリアルタイム優先度で ./test を実行できます。そうすれば、少なくとも他のユーザー空間プロセスによって中断されることはありません。

また、linux-rtパッケージをインストールすると、リアルタイム カーネルがインストールされ、スレッド化された割り込みを介して割り込みハンドラの優先度をより詳細に制御できるようになります。

于 2009-08-01T03:09:21.693 に答える
0

root として実行している場合は、sched_setscheduler() を呼び出して、自分自身にリアルタイムの優先順位を与えることができます。ドキュメントを確認してください。

于 2009-08-01T03:04:50.623 に答える
0

Linux でプリエンプティブ スケジューリングを無効にする方法があるかもしれませんが、必要ないかもしれません。/proc/<pid>/schedstatまたは他のオブジェクトからの情報を使用し/procて、プリエンプトされたタイミングを感知し、それらのタイミング サンプルを無視する可能性があります。

于 2009-08-01T03:26:18.250 に答える