2009-09-10 33 views
51

特定のpthreadのCPUアフィニティを指定したいと思います。私が今までに見つけたすべての参考文献は、スレッド(pthread_t)ではなくプロセス(pid_t)のCPUアフィニティの設定に関係しています。私はいくつかの実験をpthread_tを回してみましたが、期待通りに失敗しました。私は何か不可能なことをしようとしていますか?そうでない場合は、ポインタを送ってもらえますか?感謝万円。特定のpthreadのCPUアフィニティを設定する方法は?

答えて

36

と仮定すると、Linuxの場合:

親和性を設定するインタフェースがある - あなたはおそらく既に発見したよう:

int sched_setaffinity(pid_t pid,size_t cpusetsize,cpu_set_t *mask); 

がPIDとして0を渡すと、それが現在のスレッドに適用されますのみ、または他のスレッドにカーネルのpidをLinux固有の呼び出しで報告させてください。pid_t gettid(void);それをpidとして渡してください。 man page

The affinity mask is actually a per-thread attribute that can be adjusted independently for each of the threads in a thread group. The value returned from a call to gettid(2) can be passed in the argument pid. Specifying pid as 0 will set the attribute for the calling thread, and passing the value returned from a call to getpid(2) will set the attribute for the main thread of the thread group. (If you are using the POSIX threads API, then use pthread_setaffinity_np (3) instead of sched_setaffinity().)

+2

」を定期的にCPUアフィニティ(数秒ごと)を設定し、短いプログラムを書くことができますsched_setaffinity() " POSIX APIを使用しているかどうかはどうすればわかりますか? 'sched_setaffinity'または' pthread_setaffinity_np'を使う方法を選択するには? – javapowered

+0

RHEL 7これはmanが 'pidが0の場合、呼び出しプロセスが使用されます.'(プロセスでスレッドではありません) – javapowered

+0

@javapoweredマニュアルページの文が間違っています。 「NOTES」のセクションも読んでください。 – nos

-2

を引用

は、特定のpthreadのCPU親和性に以下の例のプログラムを見つけてください。

適切なライブラリを追加してください。

double waste_time(long n) 
{ 

    double res = 0; 
    long i = 0; 
    while (i <n * 200000) { 
     i++; 
     res += sqrt(i); 
    } 
    return res; 
} 

void *thread_func(void *param) 
{ 

    unsigned long mask = 1; /* processor 0 */ 

    /* bind process to processor 0 */ 
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), 
     &mask) <0) { 
     perror("pthread_setaffinity_np"); 
    } 

    /* waste some time so the work is visible with "top" */ 
    printf("result: %f\n", waste_time(2000)); 

    mask = 2; /* process switches to processor 1 now */ 
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), 
     &mask) <0) { 
     perror("pthread_setaffinity_np"); 
    } 

    /* waste some more time to see the processor switch */ 
    printf("result: %f\n", waste_time(2000)); 
} 


int main(int argc, char *argv[]) 
{ 

    pthread_t my_thread; 

    if (pthread_create(&my_thread, NULL, thread_func, NULL) != 0) { 
     perror("pthread_create"); 
    } 
    pthread_exit(NULL); 
} 

-D_GNU_SOURCEフラグを指定して上記のプログラムをコンパイルします。

+3

プログラムは動作しますが、表示されるいくつかの問題があります。 1)pthread_setaffinity_npは、符号なしlongではなくcpu_set_tをとります。 CPU_SET、CPU_ZEROなどを使用する必要があります。アフィニティ機能に渡す前にマスクを操作するマクロ 2)最後に、pthread_createで新しいスレッドを起動してコードのメイン部分を実行する必要はありません –

39

これは私の人生を楽にするために作ったラッパーです。その効果は、呼び出し元のスレッドがID core_idとコアに「スタック」を取得ということです:POSIX環境で使用すると、CPUがプロセスやpthreadsを使用することができ を制御するためのcpusetを使用することができます

// core_id = 0, 1, ... n-1, where n is the system's number of cores 

int stick_this_thread_to_core(int core_id) { 
    int num_cores = sysconf(_SC_NPROCESSORS_ONLN); 
    if (core_id < 0 || core_id >= num_cores) 
     return EINVAL; 

    cpu_set_t cpuset; 
    CPU_ZERO(&cpuset); 
    CPU_SET(core_id, &cpuset); 

    pthread_t current_thread = pthread_self();  
    return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); 
} 
+6

将来参照するために#define _GNU_SOURCEと# gcc 4.7.2で動作するにはが必要です。 oprofileとpthreadでテストされた、アーチのLinuxで完璧に動作しました。 – JohnTortugo

+0

また、 'gcc 4.8.1'の' sysconf'に '#include 'が必要です。 –

+0

何らかの理由で2つのコアを持つコンピュータで動作しますが、4つのコアを持つ他のコンピュータでは、次のエラーが発生します。

Segmentation fault (core dumped)
oneiros

14
//compilation: gcc -o affinity affinity.c -lpthread 

#define _GNU_SOURCE 
#include <sched.h> //cpu_set_t , CPU_SET 
#include <pthread.h> //pthread_t 
#include <stdio.h> 

void *th_func(void * arg); 

int main(void) { 
    pthread_t thread; //the thread 

    pthread_create(&thread,NULL,th_func,NULL); 

    pthread_join(thread,NULL); 

    return 0; 
} 


void *th_func(void * arg) 
{ 
    //we can set one or more bits here, each one representing a single CPU 
    cpu_set_t cpuset; 

    //the CPU we whant to use 
    int cpu = 2; 

    CPU_ZERO(&cpuset);  //clears the cpuset 
    CPU_SET(cpu , &cpuset); //set CPU 2 on cpuset 


    /* 
    * cpu affinity for the calling thread 
    * first parameter is the pid, 0 = calling thread 
    * second parameter is the size of your cpuset 
    * third param is the cpuset in which your thread will be 
    * placed. Each bit represents a CPU 
    */ 
    sched_setaffinity(0, sizeof(cpuset), &cpuset); 

    while (1); 
     ; //burns the CPU 2 

    return 0; 
} 

。 この種類の制御をCPUアフィニティと呼びます。

関数 'sched_setaffinity'はpthread IDを受け取り、 cpusetをパラメータとして受け取ります。 最初のパラメータで0を使用すると、呼び出し元のスレッド が影響を受けます。

-2

スケジューラはCPUアフィニティを適切に変更します。それを永続的に設定するには、/ procファイルシステムのcpusetを参照してください。

http://man7.org/linux/man-pages/man7/cpuset.7.html

それともその後の代わりに、(3)pthread_setaffinity_npを使用し、あなたがPOSIXスレッドのAPIを使用している場合、sched_setaffinity

関連する問題