我知道线程,但这些线程似乎运行在同一个内核中,因此我似乎无法在计算绑定操作中使用它们获得任何性能(它们对于基于套接字的内容非常有用!)
不,他们没有。除非你阻止,你的线程不阻塞,你会看到所有它们运行。只需尝试此操作(请注意,这会消耗您所有的cpu时间),它将启动16个线程,每个线程在一个繁忙的循环中计数60 s。您将看到所有线程都在运行,并且让内核失败(这样只运行一分钟,然后一切都结束了):
代码语言:javascript复制#include
#include
#include
#include
#include
#define N 16 /* had 16 cores, so I used this. Put here as many
* threads as cores you have. */
struct thread_data {
pthread_t thread_id; /* the thread id */
struct timespec end_time; /* time to get out of the tunnel */
int id; /* the array position of the thread */
unsigned long result; /* number of times looped */
};
void *thread_body(void *data)
{
struct thread_data *p = data;
p->result = 0UL;
clock_gettime(CLOCK_REALTIME, &p->end_time);
p->end_time.tv_sec += 60; /* 60 s. */
struct timespec now;
do {
/* just get the time */
clock_gettime(CLOCK_REALTIME, &now);
p->result++;
/* if you call printf() you will see them slowing, as there's a
* common buffer that forces all thread to serialize their outputs
*/
/* check if we are over */
} while ( now.tv_sec < p->end_time.tv_sec
|| now.tv_nsec < p->end_time.tv_nsec);
return p;
} /* thread_body */
int main()
{
struct thread_data thrd_info[N];
for (int i = 0; i < N; i++) {
struct thread_data *d = &thrd_info[i];
d->id = i;
d->result = 0;
printf("Starting thread %d\n", d->id);
int res = pthread_create(&d->thread_id,
NULL, thread_body, d);
if (res < 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
printf("Thread %d started\n", d->id);
}
printf("All threads created, waiting for all to finish\n");
for (int i = 0; i < N; i++) {
struct thread_data *joined;
int res = pthread_join(thrd_info[i].thread_id,
(void **)&joined);
if (res < 0) {
perror("pthread_join");
exit(EXIT_FAILURE);
}
printf("PTHREAD %d ended, with value %lu\n",
joined->id, joined->result);
}
} /* main */Linux和所有多线程系统都是一样的,它们创建一个新的执行单元(如果两者都不共享虚拟地址空间,那么它们都是进程--不完全是进程,但这解释了进程和线程之间的主要区别--),并根据需要为每个线程提供可用的处理器。线程通常被封装在进程内(它们共享--如果最近没有改变的话--进程id和虚拟内存-- linux )进程在一个单独的虚拟空间中运行,所以它们只能通过系统资源(文件、共享内存、通信套接字/管道等)共享东西。
您的测试用例的问题(您没有显示它,所以我去猜测)是,您可能会使所有线程在一个循环中,您试图打印一些东西。如果这样做,可能是每个线程在执行I/O ( printf() )时被阻塞的次数最多的时候。
Stdio FILE的问题是,它们在希望在同一个FILE上打印的所有线程之间共享一个缓冲区,并且内核序列化对同一个文件描述符的所有write(2)系统调用,因此如果您在循环中传递的大部分时间在写中被阻塞,内核(和stdio)将结束对所有打印调用的序列化,使它看起来一次只运行一个线程(所有线程都会被执行I/O的线程阻塞),这个繁忙的循环将使所有线程并行运行,并向您展示cpu是如何折叠的。