web-dev-qa-db-ja.com

LinuxでCまたはC ++からプロセスのCPUアフィニティを設定するにはどうすればよいですか?

Linuxオペレーティングシステムのc/c ++でプロセスのCPUアフィニティを設定するプログラムによる方法はありますか?.

35
jcodeninja

sched_setaffinity(2) を使用する必要があります。

たとえば、CPU 0と2だけで実行するには:

_#define _GNU_SOURCE
#include <sched.h>

cpu_set_t  mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
CPU_SET(2, &mask);
int result = sched_setaffinity(0, sizeof(mask), &mask);
_

(最初のパラメーターの_0_は現在のプロセスを意味し、制御したい他のプロセスの場合はPIDを指定します)。

sched_getcpu(3) も参照してください。

48
Alnitak

プロセスレベルでsched_setaffinityを使用するか、個々のスレッドに pthread_attr_setaffinity_np を使用します。

8
puetzk

_sched_setaffinity_ + _sched_getaffinity_最小限のC実行可能例

この例は、次の私の回答から抽出されました: CからLinuxでsched_getaffinityとsched_setaffinityを使用する方法 質問はこの質問のサブセットであるため、重複していないと思います。 _sched_getaffinity_についてのみ尋ね、C++については触れません。

この例では、アフィニティを取得して変更し、 sched_getcpu() を使用して有効になっているかどうかを確認しています。

main.c

_#define _GNU_SOURCE
#include <assert.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void print_affinity() {
    cpu_set_t mask;
    long nproc, i;

    if (sched_getaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
        perror("sched_getaffinity");
        assert(false);
    }
    nproc = sysconf(_SC_NPROCESSORS_ONLN);
    printf("sched_getaffinity = ");
    for (i = 0; i < nproc; i++) {
        printf("%d ", CPU_ISSET(i, &mask));
    }
    printf("\n");
}

int main(void) {
    cpu_set_t mask;

    print_affinity();
    printf("sched_getcpu = %d\n", sched_getcpu());
    CPU_ZERO(&mask);
    CPU_SET(0, &mask);
    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
        perror("sched_setaffinity");
        assert(false);
    }
    print_affinity();
    /* TODO is it guaranteed to have taken effect already? Always worked on my tests. */
    printf("sched_getcpu = %d\n", sched_getcpu());
    return EXIT_SUCCESS;
}
_

GitHubアップストリーム

コンパイルして実行します。

_gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
_

サンプル出力:

_sched_getaffinity = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
sched_getcpu = 9
sched_getaffinity = 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
sched_getcpu = 0
_

つまり、次のことを意味します。

  • 最初は、16個のコアすべてが有効になっていて、プロセスはコア9(10番目のコア)でランダムに実行されていました。
  • 最初のコアのみにアフィニティを設定した後、プロセスは必ずコア0(​​最初のコア)に移動されました

このプログラムをtasksetから実行するのも楽しいです。

_taskset -c 1,3 ./a.out
_

これはフォームの出力を与えます:

_sched_getaffinity = 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 
sched_getcpu = 2
sched_getaffinity = 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
sched_getcpu = 0
_

そのため、最初から親和性が制限されていたことがわかります。

これは、アフィニティがtasksetがフォークしている子プロセスによって継承されるために機能します: 子フォークされたプロセスによるCPUアフィニティの継承を防ぐ方法は?

Ubuntu16.04でテスト済み。

私は何が起こっているのかを理解するために多くの努力をしてきたので、私のような人々を助けるためにこの答えを追加します(私はlinuxmintでgccコンパイラを使用します)

#include <sched.h> 
cpu_set_t  mask;

inline void assignToThisCore(int core_id)
{
    CPU_ZERO(&mask);
    CPU_SET(core_id, &mask);
    sched_setaffinity(0, sizeof(mask), &mask);
}
int main(){
    //cal this:
    assignToThisCore(2);//assign to core 0,1,2,...

    return 0;
}

ただし、このオプションをコンパイラコマンドに追加することを忘れないでください。-D _GNU_SOURCEオペレーティングシステムが特定のコアにプロセスを割り当てる可能性があるため、GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=2,3"にあるgrubファイルにこの/etc/defaultを追加し、ターミナルでSudo update-grubを実行して、コアを予約できます。欲しいです

2
Merlin

要するに

unsigned long mask = 7; /* processors 0, 1, and 2 */
unsigned int len = sizeof(mask);
if (sched_setaffinity(0, len, &mask) < 0) {
    perror("sched_setaffinity");
}

詳細については、 CPUアフィニティ を参照してください

2
thAAAnos