sttsのソースコードMemoブログ

色々やってみた結果のMemo

Linuxでプロセスが使用するCPUを固定する方法

デュアルコアなCPUが、増えてきているので役に立つかもしれない、Linuxでプロセスが使用するCPUを固定する方法です。
シングルスレッド、シングルプロセスのプログラムを、最後の数クロックの性能を稼ぐときに役に立つかもしれません。*1
2008/02/15追記
わざわざコードを書かなくてもLinuxにCPUの割り当てを変更するコマンドが用意されていました。

taskset [options] [mask | list ] [pid | command [arg]...]

Linuxシステムプログラミング

解説

Linuxでは、sched_setaffinityシステムコールを使いプロセスが使用するCPUを指定できます。sched_setaffinityシステムコールは、Linux専用で、他のUnixでは違うシステムコールを使います。

まず、sched_getaffinityで、現状の設定を取得します。

sched_getaffinity(pid, sizeof(cpu_set_t), &cpuset);

次に、CPU_CLRとCPU_SETマクロで変数を変更します。

CPU_CLR(chgSettingCpu, &cpuset);
CPU_SET(chgSettingCpu, &cpuset);

最後に、sched_setaffinityシステムコールで、設定を変更します。

sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset)

ソース

#define _GNU_SOURCE 1
#include <stdio.h>
#include <sched.h>
#include <sys/types.h>
#include <unistd.h> // getopot
#include <stdlib.h> // exit(3)

int main (int argc, char *argv[]) {
        int res;
        int i;
        int opt;

        int chgSettingFlag = 0;
        int chgSettingCpu = 0;
        int chgSettingSet = 1;

        pid_t pid;
        cpu_set_t cpuset;

        pid = getpid();
        printf("MAX CPU_SETSIZE=%d\n", CPU_SETSIZE);
        CPU_ZERO(&cpuset);

        while ((opt=getopt(argc, argv, "p:c:s:")) != -1) {
                switch(opt) {
                case 'p':
                        pid = atoi(optarg);
                        break;
                case 'c':
                        chgSettingFlag = 1;
                        chgSettingCpu = atoi(optarg);
                        break;
                case 's':
                        chgSettingSet = atoi(optarg);
                        break;
                default:
                        fprintf(stderr, "Usage: a.out -p pid [-c CPUNUM -s [0|1] ]\n");
                        exit(99);
                        break;
                }
        }
        res = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuset);
        if (res == -1) {
                perror("Error sched_getaffinity");
                exit(99);
        }

        if (chgSettingFlag == 1 ) {
                if (chgSettingSet == 0) {
                        CPU_CLR(chgSettingCpu, &cpuset);
                } else {
                        CPU_SET(chgSettingCpu, &cpuset);
                }
                /* change cpu affinity. */
                res = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset);
                if (res == -1) {
                        perror("Error sched_setaffinity");
                        exit(99);
                }
                printf("Setted CPU:%d CPU_ISSET=%d\n", chgSettingCpu, CPU_ISSET(chgSettingCpu, &cpuset));
        } else {
                //for (i=0; i<CPU_SETSIZE; i++) {
                for (i=0; i<8; i++) {
                        printf("CPU:%d CPU_ISSET=%d\n", i, CPU_ISSET(i, &cpuset));
                }
        }
}

使い方

引数に、-p PID -c CPUNUM -s [0|1]を指定してください。
PIDは、変更したいプロセスのPIDを入力します。
CPUNUMには、変更したいCPUの番号を入れます。0から始まります。
「-s」の後には、0か1を入れます。0だと、PIDのプロセスは、CPUNUMに指定したCPUを使わなくなります。1だと使うようになります。

使えるCPU数を数えられたら便利だと思うのですが、数え方を調べていません。/proc/cpuでも見てください。

*1:今どき、シングルスレッド、シングルプロセスのプログラムは、少なそうですが。。。