커널 2.6부터 지원됩니다.
프로세스는 sched_setaffinity()가 있습니다.
쓰레드는 pthread_setaffinity_np()가 있습니다
커널의 소스에 보면 migration하는 경우에도 cpu affinity를 보고 설정된 CPU가 아니면 하지 않습니다.
그러므로 …_setaffinity()를 호출하면 해당 CPU에 고정되는 것이 맞습니다.
Hotplug시 affinity 설정된 모든 CPU가 꺼진 경우만 예외적으로 affinity를 변경합니다.
static void sched_migrate_task(task_t *p, int dest_cpu) { migration_req_t req; runqueue_t *rq; unsigned long flags; rq = task_rq_lock(p, &flags); if (!cpu_isset(dest_cpu, p->cpus_allowed) || unlikely(cpu_is_offline(dest_cpu))) goto out; .... static int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu, struct sched_domain *sd, enum idle_type idle, int *all_pinned) { /* * We do not migrate tasks that are: * 1) running (obviously), or * 2) cannot be migrated to this CPU due to cpus_allowed, or * 3) are cache-hot on their current CPU. */ if (!cpu_isset(this_cpu, p->cpus_allowed)) return 0;
아래 코드를 2.6.24, x86, 4코어에서 테스트했습니다.
( http://www.thinkingparallel.com/2006/08/18/more-information-on-pthread_setaffinity_np-and-sched_setaffinity/ 에 나온 코드를 컴파일 되도록 수정 )
/* Short test program to test the pthread_setaffinity_np * (which sets the affinity of threads to processors). * Compile: gcc pthread_setaffinity_np_test.c * -o pthread_setaffinity_np_test -lm -lpthread * Usage: ./pthread_setaffinity_test * * Open a "top"-window at the same time and see all the work * being done on CPU 0 first and after a short wait on CPU 1. * Repeat with different numbers to make sure, it is not a * coincidence. */ #include <stdio.h> #include <math.h> #include <unistd.h> #define __USE_GNU #include <pthread.h> 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), (cpu_set_t *)&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 */ sleep(2); if (pthread_setaffinity_np(pthread_self(), sizeof(mask), (cpu_set_t *)&mask) <0) { perror("pthread_setaffinity_np"); } /* waste some more time to see the processor switch */ printf("result: %f\n", waste_time(2000)); return 0; } 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); pthread_join(my_thread, NULL); return 0; }
———————————
프로세스의 경우 소스는 다음과 같습니다.
/* Short test program to test sched_setaffinity * (which sets the affinity of processes to processors). * Compile: gcc sched_setaffinity_test.c * -o sched_setaffinity_test -lm * Usage: ./sched_setaffinity_test * * Open a "top"-window at the same time and see all the work * being done on CPU 0 first and after a short wait on CPU 1. * Repeat with different numbers to make sure, it is not a * coincidence. */ #include <stdio.h> #include <math.h> #include <unistd.h> #define __USE_GNU #include <sched.h> double waste_time(long n) { double res = 0; long i = 0; while(i <n * 200000) { i++; res += sqrt (i); } return res; } int main(int argc, char **argv) { unsigned long mask = 1; /* processor 0 */ /* bind process to processor 0 */ if (sched_setaffinity(0, sizeof(mask), (cpu_set_t*)&mask) <0) { perror("sched_setaffinity"); } /* 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 (sched_setaffinity(0, sizeof(mask), (cpu_set_t*)&mask) <0) { perror("sched_setaffinity"); } /* waste some more time to see the processor switch */ printf ("result: %f\n", waste_time (2000)); return 0; }