C 比较各种pthread构造的性能

C 比较各种pthread构造的性能,c,performance,parallel-processing,pthreads,execution-time,C,Performance,Parallel Processing,Pthreads,Execution Time,我需要通过设计一些实验来比较各种pthread结构的性能,比如互斥、信号量、读写锁以及相应的串行程序。主要问题是决定如何测量分析代码的执行时间? 我读过一些C函数,如clock()、gettimeofday()等。根据我的理解,我们可以使用clock()来获得程序使用的实际CPU周期数(通过减去我们要测量其时间的代码开始和结束时函数返回的值),gettimeofday()返回程序执行的挂钟时间 但问题是,总CPU周期对我来说似乎不是一个好的标准,因为它会将所有并行运行线程所花费的CPU时间相加(

我需要通过设计一些实验来比较各种pthread结构的性能,比如互斥、信号量、读写锁以及相应的串行程序。主要问题是决定如何测量分析代码的执行时间?

我读过一些C函数,如clock()、gettimeofday()等。根据我的理解,我们可以使用clock()来获得程序使用的实际CPU周期数(通过减去我们要测量其时间的代码开始和结束时函数返回的值),gettimeofday()返回程序执行的挂钟时间

但问题是,总CPU周期对我来说似乎不是一个好的标准,因为它会将所有并行运行线程所花费的CPU时间相加(因此时钟()对我来说并不好)。另外,挂钟时间也不好,因为可能有其他进程在后台运行,所以时间最终取决于线程的调度方式(因此gettimeofday()在我看来也不好)


我所知道的其他一些函数也很可能与上面两个函数的功能相同。因此,我想知道是否有一些函数可以用于我的分析,或者我在上面的结论中有错吗?

我不确定数组求和是否是一个好的测试,在多线程中求和数组不需要任何互斥等,每个线程只需求和数组的一个专用部分,而且,对于很少的CPU计算,存在大量的内存访问。示例(编译时给出了SZ和NTHREADS的值),测量的时间为实时(单调):

(由1000.000.000个元素组成的阵列)

正如您所看到的,即使执行时间不除以线程数,瓶颈也可能是从以下位置访问内存:

我相信
clock()
在某个地方被实现为
clock\u gettime(clock\u PROCESS\u CPUTIME\u ID
,但我看到它是在glibc中使用
times()
实现的

因此,如果您想测量特定于线程的CPU时间,可以在GNU/Linux系统上使用
clock\u gettimer(clock\u thread\u CPUTIME\u ID,

永远不要用
gettimeofday
clock\u gettime(clock\u REALTIME
来衡量程序的执行情况。甚至不要想这个。
gettimeofday
是“挂钟”—你可以把它挂在你房间的墙上。如果你想衡量时间的流动,忘记
gettimeofday


如果您愿意,您甚至可以通过在线程内部使用它返回的
clock\u id
值和
clock\u gettime
来保持完全的位置兼容。您的执行日志如何?您的操作系统是什么?如果您想比较单线程/多线程比较实时而不是cpu时间,我使用的是Linux,执行时间是多长?h你有多少cpu/核心?我必须比较不同的输入大小-例如,我必须对一个数组求和,然后我必须改变大小,可能是10^7、10^8、10^9。你应该显示你尝试的代码。关于测量时间的方法,你应该使用
clock\u gettime()
\u rdtsc()
。不要忘记禁用CPU频率更改。始终在编译器上至少使用
-O2
。执行多种度量并使用统计方法删除异常值:修剪平均值,甚至是最小值,这样更简单,结果更稳定。不应使用
gettimeofday()
用于性能测量。任何ntp同步都会破坏您的测量。@AlainMerigot测量的执行时间会有变化,但可能不是因为ntp,时钟足够好,追赶速度很小。对我来说,必须测量实时,而不是CPUtime@AlainMerigot不管怎样,我改成了单调的时间n你想要测量的,对我来说是实时的,因为这是我感觉到的时间,如果我需要1分钟来加载我的程序,我不在乎它需要1秒来执行,对我来说时间是1分钟而不是1秒;-)然后使用
CLOCK\u单调的
,而不是
gettimeofday
gettimeofday
是挂钟,而不是“测量间隔时钟”。它可以跳转。如果您使用
gettimeofday
来测量程序的执行情况,请不要惊讶于看到负的时间间隔。或者错误的时间间隔。它可以跳转。
gettimeofday
仅适用于与UTC同步的漂亮用户时钟时间。因为一旦闰秒开始,您的测量就会错误。或者
ntp将启动并同步系统-您的测量结果将出错。
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

static int Arr[SZ];

void * thSum(void * a)
{
  int s = 0, i;
  int sup = *((int *) a) + SZ/NTHREADS;

  for (i = *((int *) a); i != sup; ++i)
    s += Arr[i];

  *((int *) a) = s;
}

int main()
{
  int i;

  for (i = 0; i != SZ; ++i)
    Arr[i] = rand();

  struct timespec t0, t1;

  clock_gettime(CLOCK_MONOTONIC, &t0);

  int s = 0;

  for (i = 0; i != SZ; ++i)
    s += Arr[i];

  clock_gettime(CLOCK_MONOTONIC, &t1);
  printf("mono thread : %d %lf\n", s,
         (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec)/1000000000.0);

  clock_gettime(CLOCK_MONOTONIC, &t0);

  int n[NTHREADS];
  pthread_t ths[NTHREADS];

  for (i = 0; i != NTHREADS; ++i) {
    n[i] = SZ / NTHREADS * i;
    if (pthread_create(&ths[i], NULL, thSum, &n[i])) {
      printf("cannot create thread %d\n", i);
      return -1;
    }
  }

  int s2 = 0;

  for (i = 0; i != NTHREADS; ++i) {
    pthread_join(ths[i], NULL);
    s2 += n[i];
  }

  clock_gettime(CLOCK_MONOTONIC, &t1);
  printf("%d threads : %d %lf\n", NTHREADS, s2,
         (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec)/1000000000.0);
}
/tmp % gcc -DSZ=100000000 -DNTHREADS=2 -O3 s.c -lpthread -lrt
/tmp % ./a.out
mono thread : 563608529 0.035217
2 threads : 563608529 0.020407
/tmp % ./a.out
mono thread : 563608529 0.034991
2 threads : 563608529 0.022659
/tmp % gcc -DSZ=100000000 -DNTHREADS=4 -O3 s.c -lpthread -lrt
/tmp % ./a.out
mono thread : 563608529 0.035212
4 threads : 563608529 0.014234
/tmp % ./a.out
mono thread : 563608529 0.035184
4 threads : 563608529 0.014163
/tmp % gcc -DSZ=100000000 -DNTHREADS=8 -O3 s.c -lpthread -lrt
/tmp % ./a.out
mono thread : 563608529 0.035229
8 threads : 563608529 0.014971
/tmp % ./a.out
mono thread : 563608529 0.035142
8 threads : 563608529 0.016248
/tmp % gcc -DSZ=1000000000 -DNTHREADS=2 -O3 s.c -lpthread -lrt
/tmp % ./a.out
mono thread : -1471389927 0.343761
2 threads : -1471389927 0.197303
/tmp % ./a.out
mono thread : -1471389927 0.346682
2 threads : -1471389927 0.197669
/tmp % gcc -DSZ=1000000000 -DNTHREADS=4 -O3 s.c -lpthread -lrt
/tmp % ./a.out
mono thread : -1471389927 0.346859
4 threads : -1471389927 0.130639
/tmp % ./a.out
mono thread : -1471389927 0.346506
4 threads : -1471389927 0.130751
/tmp % gcc -DSZ=1000000000 -DNTHREADS=8 -O3 s.c -lpthread -lrt
/tmp % ./a.out
mono thread : -1471389927 0.346954
8 threads : -1471389927 0.123572
/tmp % ./a.out
mono thread : -1471389927 0.349652
8 threads : -1471389927 0.127059
   CLOCK_PROCESS_CPUTIME_ID (since Linux 2.6.12)
          Per-process CPU-time clock (measures CPU time consumed by all
          threads in the process).

   CLOCK_THREAD_CPUTIME_ID (since Linux 2.6.12)
          Thread-specific CPU-time clock.