什么是Pthreads?
为什么要用Pthreads?
Platform | fork() | pthread_create() | ||||
---|---|---|---|---|---|---|
real | user | sys | real | user | sys | |
AMD 2.3 GHz Opteron (16cpus/node) | 12.5 | 1.0 | 12.5 | 1.2 | 0.2 | 1.3 |
AMD 2.4 GHz Opteron (8cpus/node) | 17.6 | 2.2 | 15.7 | 1.4 | 0.3 | 1.3 |
IBM 4.0 GHz POWER6 (8cpus/node) | 9.5 | 0.6 | 8.8 | 1.6 | 0.1 | 0.4 |
IBM 1.9 GHz POWER5 p5-575 (8cpus/node) | 64.2 | 30.7 | 27.6 | 1.7 | 0.6 | 1.1 |
IBM 1.5 GHz POWER4 (8cpus/node) | 104.5 | 48.6 | 47.2 | 2.1 | 1.0 | 1.5 |
INTEL 2.4 GHz Xeon (2 cpus/node) | 54.9 | 1.5 | 20.8 | 1.6 | 0.7 | 0.9 |
INTEL 1.4 GHz Itanium2 (4 cpus/node) | 54.5 | 1.1 | 22.2 | 2.0 | 1.2 | 0.6 |
==============================================================================
C Code for fork() creation test
==============================================================================
#include < stdio.h >
#include < stdlib.h >
#define NFORKS 50000
void do_nothing() {
int i;
i = 0 ;
}
int main( int argc, char * argv[]) {
int pid, j, status;
for (j = 0 ; j < NFORKS; j ++ ) {
/* ** error handling ** */
if ((pid = fork()) < 0 ) {
printf ( " fork failed with error code= %d\n " , pid);
exit( 0 );
}
/* ** this is the child of the fork ** */
else if (pid == 0 ) {
do_nothing();
exit( 0 );
}
/* ** this is the parent of the fork ** */
else {
waitpid(pid, status, 0 );
}
}
}
==============================================================================
C Code for pthread_create() test
==============================================================================
#include < pthread.h >
#include < stdio.h >
#include < stdlib.h >
#define NTHREADS 50000
void * do_nothing( void * null ) {
int i;
i = 0 ;
pthread_exit(NULL);
}
int main( int argc, char * argv[]) {
int rc, i, j, detachstate;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init( & attr);
pthread_attr_setdetachstate( & attr, PTHREAD_CREATE_JOINABLE);
for (j = 0 ; j < NTHREADS; j ++ ) {
rc = pthread_create( & tid, & attr, do_nothing, NULL);
if (rc) {
printf( " ERROR; return code from pthread_create() is %d\n " , rc);
exit( - 1 );
}
/* Wait for the thread */
rc = pthread_join(tid, NULL);
if (rc) {
printf( " ERROR; return code from pthread_join() is %d\n " , rc);
exit( - 1 );
}
}
pthread_attr_destroy( & attr);
pthread_exit(NULL);
}
- CPU与I/O的重叠协作:例如,一个程序可能分多段对I/O进行长操作,当一个线程正在等待一个I/O系统调用完成时,CPU可以用其它线程进行现有的密集工作;
- 优先级/实时调度:可预定更重要的任务取代或者中断低优先级的任务;
- 异步事件处理:一些不确定次数和持续时间的服务事件是交叉执行的任务。例如,Web服务器可以在应答前一个传输数据的请求时候,处理新的数据请求。
- MPI库经常通过共享内存来实现on-node任务通讯,这样,就必须至少调用一次内存拷贝操作(进程对进程的);
- 对于Pthreads,不存在中间(intermediate)的内存拷贝,因为在一个进程中,线程共享相同的地址空间。本身也没有数据传输,它成为了一个从高速缓存到CPU或是内存到CPU带宽式的传输情况,它们的速度更快;
- 以下是比较列表:
Platform MPI Shared Memory Bandwidth
(GB/sec)Pthreads Worst Case
Memory-to-CPU Bandwidth
(GB/sec)AMD 2.3 GHz Opteron 1.8 5.3 AMD 2.4 GHz Opteron 1.2 5.3 IBM 1.9 GHz POWER5 p5-575 4.1 16 IBM 1.5 GHz POWER4 2.1 4 Intel 2.4 GHz Xeon 0.3 4.3 Intel 1.4 GHz Itanium 2 1.8 6.4
附注:
SMP——Symmetrical Multi-Processing,对称多处理系统;
MPI——Message Passing Interface,参照http://www-unix.mcs.anl.gov/mpi/mpich/。