Viewer писал(а):С многопоточностью в Linux, pthread примерно ясно, но речь здесь совершенно не об этом, если я правильно понимаю речь идет о физических (или логических) ядрах процессора. Хотя с принципом - "можно все" спорить бесполезно, но весьма было бы любопытно увидеть работоспособный пример с запуском потока на конкретном ядре (скажем 2-м), да еще чтоб он был работоспособен хотябы на 10% девайсов.
Вопервых распределяются не потоки, а процессы.
[syntax=c]
//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;
}
[/syntax]
или просто для примера ( так делать не надо ):
[syntax=c]
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);
}
[/syntax]
для более общей картины можно посмотреть на такое:
[syntax=c]
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>
#include <unistd.h>
int getNumberOfCpus( void )
{
long nprocs = -1;
long nprocs_max = -1;
# ifdef _SC_NPROCESSORS_ONLN
nprocs = sysconf( _SC_NPROCESSORS_ONLN );
if ( nprocs < 1 )
{
//std::cout << "Could not determine number of CPUs on line. Error is " << strerror( errno ) << std::endl;
return 0;
}
nprocs_max = sysconf( _SC_NPROCESSORS_CONF );
if ( nprocs_max < 1 )
{
//std::cout << "Could not determine number of CPUs in host. Error is " << strerror( errno ) << std::endl;
return 0;
}
//std::cout << nprocs < " of " << nprocs_max << " online" << std::endl;
return nprocs;
#else
//std::cout << "Could not determine number of CPUs" << std::endl;
return 0;
#endif
}
void *pthread_Message( void *ptr )
{
sleep(10);
char *message;
message = (char *) ptr;
printf("%s \n", message);
cpu_set_t l_cpuSet;
int l_maxCpus;
int j;
unsigned long l_cpuBitMask;
CPU_ZERO( &l_cpuSet );
printf("get affinity %d\n",pthread_getaffinity_np(pthread_self() , sizeof( cpu_set_t ), &l_cpuSet ));
// printf("cpuset %d\n",l_cpuSet);
printf (" thread id %u\n", pthread_self());
if ( pthread_getaffinity_np(pthread_self() , sizeof( cpu_set_t ), &l_cpuSet ) == 0 )
for (int i = 0; i < 4; i++)
if (CPU_ISSET(i, &l_cpuSet))
printf("XXXCPU: CPU %d\n", i);
for (long i=0; i< 10000000000; ++i);
}
int main()
{
pthread_t thread1, thread2, thread3, thread4;
pthread_t threadArray[4];
cpu_set_t cpu1, cpu2, cpu3, cpu4;
const char *thread1Msg = "Thread 1";
const char *thread2Msg = "Thread 2";
const char *thread3Msg = "Thread 3";
const char *thread4Msg = "Thread 4";
int thread1Create, thread2Create, thread3Create, thread4Create, i, temp;
thread1Create = pthread_create(&thread1, NULL, &pthread_Message, (void*)thread1Msg);
sleep(1);
thread2Create = pthread_create(&thread2, NULL, &pthread_Message, (void*)thread2Msg);
sleep(1);
thread3Create = pthread_create(&thread3, NULL, &pthread_Message, (void*)thread3Msg);
sleep(1);
thread4Create = pthread_create(&thread4, NULL, &pthread_Message, (void*)thread4Msg);
CPU_ZERO(&cpu1);
CPU_SET(0, &cpu1);
temp = pthread_setaffinity_np(thread1, sizeof(cpu_set_t), &cpu1);
printf("setaffinity=%d\n", temp);
printf("Set returned by pthread_getaffinity_np() contained:\n");
for (i = 0; i < CPU_SETSIZE; i++)
if (CPU_ISSET(i, &cpu1))
printf("CPU1: CPU %d\n", i);
CPU_ZERO(&cpu2);
CPU_SET(1, &cpu2);
temp = pthread_setaffinity_np(thread2, sizeof(cpu_set_t), &cpu2);
for (i = 0; i < CPU_SETSIZE; i++)
if (CPU_ISSET(i, &cpu2))
printf("CPU2: CPU %d\n", i);
CPU_ZERO(&cpu3);
CPU_SET(2, &cpu3);
temp = pthread_setaffinity_np(thread3, sizeof(cpu_set_t), &cpu3);
for (i = 0; i < CPU_SETSIZE; i++)
if (CPU_ISSET(i, &cpu3))
printf("CPU3: CPU %d\n", i);
CPU_ZERO(&cpu4);
CPU_SET(3, &cpu4);
temp = pthread_setaffinity_np(thread4, sizeof(cpu_set_t), &cpu4);
for (i = 0; i < CPU_SETSIZE; i++)
if (CPU_ISSET(i, &cpu4))
printf("CPU4: CPU %d\n", i);
// pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu1);
// pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu1);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
pthread_join(thread4, NULL);
return 0;
}
[/syntax]
Я повторю реализованна модель posix на уровне ядра, никакого вообще отношения к типу девайса -это не имеет, просто ядра доступны или нет, это определяется на уровне заголовков.
P.S. кстати именно posix модель обеспечивает в первую очередь переносимость и абсолютную независимость от типа устройтсва.