我正在编写一个简单的应用程序,它使用线程来提高性能。问题是,这个应用程序在windows上运行良好,使用的是我的CPU拥有的2个内核。但当我在Linux上执行时,似乎只使用了1个内核。
我不明白为什么会这样。
这是我的代码,C++:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
void* function(void*)
{
int i=0;
for(i=0; i<1110111; i++)
rand();
return 0;
}
void withOutThreads(void)
{
function(0);
function(0);
}
void withThreads(void)
{
pthread_t* h1 = new pthread_t;
pthread_t* h2 = new pthread_t;
pthread_attr_t* atr = new pthread_attr_t;
pthread_attr_init(atr);
pthread_attr_setscope(atr,PTHREAD_SCOPE_SYSTEM);
pthread_create(h1,atr,function,0);
pthread_create(h2,atr,function,0);
pthread_join(*h1,0);
pthread_join(*h2,0);
pthread_attr_destroy(atr);
delete h1;
delete h2;
delete atr;
}
int main(void)
{
int ini,tim;
ini = clock();
withOutThreads();
tim = (int) ( 1000*(clock()-ini)/CLOCKS_PER_SEC );
printf("Time Sequential: %d ms\n",tim);
fflush(stdout);
ini = clock();
withThreads();
tim = (int) ( 1000*(clock()-ini)/CLOCKS_PER_SEC );
printf("Time Concurrent: %d ms\n",tim);
fflush(stdout);
return 0;
}Linux上的输出:
Time Sequential: 50 ms
Time Concurrent: 1610 msWindows上的输出:
Time Sequential: 50 ms
Time Concurrent: 30 ms发布于 2011-02-22 01:02:27
在windows和linux上,clock()的工作方式不同,所以不要用它来测量时间。在linux上,它测量CPU时间,在windows上,它测量挂钟时间。理想情况下,这些在此测试用例中应该是相同的,但您应该使用平台之间一致的东西来测量时间。例如gettimeofday()
linux()在上序列化你的线程, rand()拥有一个内部锁以保证线程安全。rand()手册页声明rand()既不是线程安全的,也不是可重入的,但是至少在最近的glibc中的代码在调用周围获得了一个锁。我不确定windows是如何处理这个问题的,要么它根本不是线程安全的,要么就是它使用了线程局部变量。
在linux上使用rand_r,或者找到一些更好的CPU利用率函数来测量。
void* function(void*)
{
unsigned int seed = 42;
int i=0;
for(i=0; i<1110111; i++)
rand_r(&seed);
return 0;
}发布于 2011-02-22 01:05:39
问题是Linux多线程版本或rand()锁定了一个互斥锁。将函数更改为:
void* function(void*)
{
int i=0;
unsigned rand_state = 0;
for(i=0; i<1110111; i++)
rand_r(&rand_state);
return 0;
}输出:
Time Sequential: 10 ms
Time Concurrent: 10 ms发布于 2015-01-13 06:30:24
Linux“看到”像进程一样的线程,这意味着所有的进程都是一个线程的线程。
在进程表(task_struct)中,当我们创建一个进程时,它被创建为PID,当我们创建第二个线程时,PID成为TGID (线程组ID),并且每个线程都获得一个TID (线程id)。
在userland中,我们将只看到第一线程(使用ps aux),但是如果我们执行"ps -eLf“,我们将看到一个名为LWP (轻量级进程)的新列,它是TID。
例如:$ ps -eLf
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1356 1 1356 0 4 2014 ? 00:00:00 /sbin/rsyslogd
root 1356 1 1357 0 4 2014 ? 00:02:01 /sbin/rsyslogd
root 1356 1 1359 0 4 2014 ? 00:01:55 /sbin/rsyslogd
root 1356 1 1360 0 4 2014 ? 00:00:00 /sbin/rsyslogd
dbus 1377 1 1377 0 1 2014 ? 00:00:00 dbus-daemon
正如我们所看到的,PID是相同的,但真正的PID是LWP (TID)。当进程只有一个线程(如dbus守护进程)时,PID = LWP (TID)
在内部,内核总是像PID一样使用TID。
在此之后,内核将能够使用调度,每个线程使用真正的并行性。
https://stackoverflow.com/questions/5068697
复制相似问题