Как установить сродство процессора конкретного pthread? - PullRequest
53 голосов
/ 11 сентября 2009

Я бы хотел указать привязку процессора к конкретному pthread. Все ссылки, которые я нашел до сих пор, касаются установки привязки к процессору (pid_t), а не потоку (pthread_t). Я попробовал некоторые эксперименты, передавая pthread_t, и, как и ожидалось, они провалились. Я пытаюсь сделать что-то невозможное? Если нет, можете ли вы отправить указатель, пожалуйста? Спасибо миллион.

Ответы [ 5 ]

53 голосов
/ 20 июля 2012

Это обертка, которую я сделал, чтобы облегчить мне жизнь. Это приводит к тому, что вызывающий поток «застревает» в ядре с идентификатором core_id:

// 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);
}
41 голосов
/ 11 сентября 2009

Предположим, Linux:

Интерфейс для настройки соответствия - как вы, вероятно, уже обнаружили:

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

Передача 0 в качестве pid, и он будет применяться только к текущему потоку, или же другой поток сообщит свой pid ядра с помощью специального вызова linux pid_t gettid (void); и передать это как pid.

Цитирование справочной страницы

Маска сходства на самом деле является атрибутом для каждого потока, который может быть корректируется независимо для каждого из темы в группе потоков. Значение вернулся из звонка в gettid (2) может передаваться в аргументе pid. Указание pid как 0 установит атрибут для вызывающего потока, и Передача значения, возвращенного из вызова getpid (2) установит атрибут для основной нити нити группа. (Если вы используете POSIX API потоков, затем используйте pthread_setaffinity_np (3) вместо sched_setaffinity ().)

19 голосов
/ 20 февраля 2014
//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;
}

В среде POSIX вы можете использовать cpusets для управления какие процессоры могут использоваться процессами или потоками. Этот тип управления называется привязкой к процессору.

Функция 'sched_setaffinity' получает идентификаторы pthread и процессор в качестве параметра. Когда вы используете 0 в первом параметре, вызывающий поток будет затронуто

0 голосов
/ 30 июля 2014

Планировщик изменит сродство процессора, как сочтет нужным; чтобы установить его постоянно, см. cpuset в файловой системе / proc.

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

Или вы можете написать короткую программу, которая периодически устанавливает сродство процессора (каждые несколько секунд) с помощью sched_setaffinity

0 голосов
/ 27 апреля 2012

Найдите приведенный ниже пример программы для cpu-affinity определенного pthread.

Пожалуйста, добавьте соответствующие библиотеки.

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.

...