0

Linux プロセスを同じコンピューターの別のコアに移行するのにかかる費用を見積もる必要があります。プロセスを移行するために sched_setaffinity システム コールを使用していますが、移行が常に瞬時に行われるとは限らないことに気付きました。これが私の要件です。

さらに詳しく説明すると、単純な計算を 2 回ずつ行う C プログラムを作成しています。1 回目は移行なし、2 回目は移行ありです。2 つのタイムスタンプの差を計算すると、移行のオーバーヘッドを大まかに見積もることができます。ただし、現在のプロセスを移行して移行が行われるまで待つ方法を理解する必要があります

#define _GNU_SOURCE
#define _POSIX_C_SOURCE 199309L

#include <assert.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <stdint.h>

//Migrates the process
int migrate(pid_t pid) {
    const int totCPU = 8;
    const int nextCPU = (sched_getcpu() +1) % totCPU;

    cpu_set_t target;
    CPU_SET(nextCPU, &target);
    if(sched_setaffinity(pid, sizeof(target), &target) < 0)
        perror("Setaffinity");

    return nextCPU;
}

int main(void) {
    long i =0;
    const long iterations = 4;
    uint64_t total_sequential_delays = 0;
    uint64_t total_migration_delays = 0;
    uint64_t delta_us;

    for(int i=0; i < iterations; i++) {
        struct timespec start, end;

        //Migration benchmark only happens in odd iterations
        bool do_migration = i % 2 == 1;
        //Start timestamp
        clock_gettime(CLOCK_MONOTONIC_RAW, &start);
        //Target CPU to migrate
        int target;
        if(do_migration) {
            target = migrate(0);
            //if current CPU is not the target CPU
            if(target != sched_getcpu()) {
                do {
                    clock_gettime(CLOCK_MONOTONIC_RAW, &end);
                }
                while(target != sched_getcpu());
            }
        }

        //Simple computation 
        double k = 5;
        for(int j = 1; j <= 9999; j++) {
            k *= j / (k-3);
        }

        //End timestamp
        clock_gettime(CLOCK_MONOTONIC_RAW, &end);

        //Elapsed time
        delta_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
        if(do_migration) total_migration_delays += delta_us;
        else total_sequential_delays += delta_us;
    }

    //Compute the averages
    double avg_migration = total_migration_delays / iterations;
    double avg_sequential = total_sequential_delays / iterations;

    //Print them
    printf("\navg_migration=%f, avg_sequential=%f",avg_migration,avg_sequential);

    return EXIT_SUCCESS;
}

ここでの問題は、do-while ループ (行 46 ~ 49) が永久に実行される場合があることです。

4

2 に答える 2

0

Linux プロセスを同じコンピューターの別のコアに移行するのにかかる費用を見積もる必要があります。

OK、コストは次のように見積もることができます。

  • 新しい CPU アフィニティを設定し、"yield" または " sleep(0)" を実行してタスクの切り替え/再スケジュールを強制するのにかかった時間 (タスク切り替えのオーバーヘッドなどを含む)。

  • 「古い CPU ではキャッシュされたが、新しい CPU ではまだキャッシュされていない」メモリ アクセスごとのキャッシュ ミスのコスト

  • 将来の「仮想から物理への変換は古い CPU にキャッシュされたが、新しい CPU にはまだキャッシュされていない」メモリアクセスごとの TLB ミスのコスト

  • NUMA ペナルティ

  • 負荷分散の問題 (たとえば、「負荷の軽い」CPU またはコアから「他のプロセスによる負荷の高い」CPU またはコアへの移行は、負荷分散を修正するためにカーネルが他のプロセスを別の CPU に移行することを決定するコストなど、重大なパフォーマンスの問題を引き起こす可能性があります。 、他のプロセスによって支払われるコスト/オーバーヘッドは、おそらくプロセスの移行によって発生する総コストに含まれる必要があります)。

ご了承ください:

a) 複数レベルのキャッシュ (トレース キャッシュ、命令キャッシュ、L1 データ キャッシュ、L2 データ キャッシュなど) があり、一部のキャッシュは一部の CPU 間で共有されます (たとえば、L1 は同じコア内の論理 CPU 間で共有される場合があり、L2 は場合によっては共有される場合があります)。 2 コアで共有される場合、L3 は 8 コアで共有される場合があります)。

b) TLB ミスのコストは多くのことに依存します (たとえば、カーネルが PCID 機能なしでメルトダウンの軽減策を使用していて、とにかくシステム コールごとに TLB 情報を吹き飛ばしている場合)。

c) NUMA ペナルティはレイテンシ コストです。以前の CPU (以前の NUMA ノード用) に割り当てられた RAM へのすべてのアクセス (キャッシュ ミスなど) は、新しい/現在の CPU に割り当てられた RAM へのアクセスよりもレイテンシが高くなります (正しい)。 NUMA ノード)。

d) すべてのキャッシュ ミス コスト、TLB ミス コスト、および NUMA ペナルティは、メモリ アクセス パターンに依存します。メモリ アクセスがないベンチマークは誤解を招く可能性があります。

e) キャッシュ ミス コスト、TLB ミス コスト、および NUMA ペナルティは、関係するハードウェアに大きく依存します。たとえば、ある「高速 RAM を備えた低速 CPU で NUMA を使用しない」コンピュータのベンチマークは、別の「低速 RAM を備えた高速 CPU」にはまったく関係ありません。および多くの NUMA ドメイン」コンピューター。同様に、どの CPU に大きく依存します (たとえば、CPU #0 から CPU #1 への移行はほとんど費用がかからず、CPU #0 から CPU #15 への移行は非常に費用がかかる場合があります)。

プロセスを移行するために sched_setaffinity システム コールを使用していますが、移行が常に瞬時に行われるとは限らないことに気付きました。これが私の要件です。

sleep(0);」の後に「sched_setaffinity();」を付けます。

于 2019-10-29T20:04:54.857 に答える