将工作分配到更多线程需要更多时间,为什么?

非洲

我有一个小的C程序,它使用monte-carlo -simulation计算pi,基本上,它只是测试随机点[x,y]是在圆内还是在圆外。

要近似pi,我必须使用大量样本n,它们的正比例复杂度为O(n)因此,尝试计算大量样本n时,我实现了POSIX线程api以使计算能力并行化。

我的代码如下所示:

pthread_t worker[nthreads]; /* creates workers for each thread */
struct param aparam[nthreads]; /* struct param{ long* hits; long rounds; }; */
long nrounds = nsamples / nthreads; /* divide samples to subsets of equal rounds per thread */

for (int i = 0; i < nthreads; ++i) { /* loop to create threads */
    aparam[i].hits = 0;
    aparam[i].rounds = nrounds;
    pthread_create(&worker[i], NULL, calc_pi, &aparam[i]); /* calls calc_pi(void* vparam){}  */ 
}

long nhits = 0;
for (int j = 0; j < nthreads; ++j) { /* collects results */
    pthread_join(worker[j], NULL);
    nhits += (long)aparam[j].hits; /* counts hits inside the cicrle */
}

这是每个线程在做的事情:

void* calc_pi(void* vparam)
{ /* counts hits inside a circle */
    struct param *iparam;
    iparam = (struct param *) vparam;
    long hits = 0;
    float x, y, z;
    for (long i = 0; i < iparam->rounds; ++i) {
        x = (float)rand()/RAND_MAX;
        y = (float)rand()/RAND_MAX;
        z = x * x + y * y;
        if (z <= 1.f) /* circle radius of 1 */
            ++hits;
    }
    iparam->hits = (long*)hits;
    return NULL;
}

现在我有一个奇怪的发现。在具有相同样本集n和线程数量i的情况下,此程序将花费更多的时间而不是更少的时间

以下是一些平均运行时间(可重现):

-------------------------------------------------
| Threads[1] | Samples[1] | Rounds[1] | Time[s] |
-------------------------------------------------
|        32  |  268435456 |   8388608 |    118  |
|        16  |  268435456 |  16777216 |    106  |
|         8  |  268435456 |  33554432 |    125  |
|         4  |  268435456 |  67108864 |    152  |
|         2  |  268435456 | 134217728 |     36  |
|         1  |  268435456 | 268435456 |     15  |
-------------------------------------------------

例如,为什么两个线程执行相同的工作要比一个线程花费更多的时间?我的假设是,将工作划分为两个线程可以将时间至少减少50%。

符合GCC 4.9.1和以下标志:

gcc -O2 -std=gnu11 -pthread pipa.c -lpthread -o pipa

我的硬件是双核Intel Xeon E5520(2个处理器,每个4核)@ 2.26 GHz,禁用超线程,运行带有2.6.18内核的科学linux。

有任何想法吗?

假人00001

您的线程执行的最昂贵的操作是调用rand()rand()是一个幼稚,简单且通常不可扩展的MT功能(因为它保证了相同的种子可以产生相同的随机序列)。我认为里面的锁rand()正在序列化所有线程。(*)

确认是否存在问题的一个简单技巧是,在调试器下启动程序,然后执行几次:暂停它,捕获线程的堆栈跟踪,然后继续。无论在堆栈跟踪中最常出现的是什么,都是瓶颈。

(*)使锁争用导致额外的性能损失的事实使其变得更加缓慢。同样,许多线程增加了进程调度和上下文切换的额外开销。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么 ForkJoinPool.commonPool().execute(runnable) 运行线程需要更多时间

来自分类Dev

在JAVA中创建更多线程以并行化线性搜索会消耗更多时间

来自分类Dev

为什么长字面量计算需要更多时间?

来自分类Dev

为什么 numpy 数组比列表花费更多时间?

来自分类Dev

普通选择查询需要更多时间

来自分类Dev

Python多处理需要更多时间

来自分类Dev

为什么JSF 2.2需要花费更多时间在Wildfly上部分渲染ajax请求

来自分类Dev

为什么Azure ML Studio(经典)需要花费更多时间来执行Python脚本?

来自分类Dev

当文件更多时,FTP需要花费更多时间来消耗消息-ESB

来自分类Dev

为什么通过主机名执行ping操作比通过IP地址花费更多时间?

来自分类Dev

Neo4j插入需要更多时间

来自分类Dev

春季休眠需要更多时间的任何原因?

来自分类Dev

注销:与同步FileAppender相比,AsyncAppender需要更多时间

来自分类Dev

C#需要更多时间进行首次执行

来自分类Dev

Neo4j插入需要更多时间

来自分类Dev

为什么在启动更多进程时基于Fortran的MPI例程需要更多的计算时间

来自分类Dev

为什么在启动更多进程时基于Fortran的MPI例程需要更多的计算时间

来自分类Dev

为什么在E_OUTOFMEMORY后跟“无法创建更多线程”?

来自分类Dev

为什么开普勒GK107中的更多线程出现较慢的算法?

来自分类Dev

尽管使用了更多线程,为什么我的程序变慢了?

来自分类Dev

为什么我的 Eigen 代码不能使用更多线程进行缩放

来自分类Dev

为什么SOAP比REST需要更多的带宽和更多的资源?

来自分类Dev

为什么User.first会花更多时间第一次查询数据库?

来自分类Dev

为什么单片内核需要更多的重启?

来自分类Dev

为什么wait()函数需要更多参数?

来自分类Dev

为什么单片内核需要更多的重启?

来自分类Dev

检查 Parallel.Foreach 中的线程所花费的时间,如果花费更多时间则退出

来自分类Dev

为什么多线程版本需要与单线程版本相同的时间?

来自分类Dev

MSSQL参数消耗更多时间

Related 相关文章

  1. 1

    为什么 ForkJoinPool.commonPool().execute(runnable) 运行线程需要更多时间

  2. 2

    在JAVA中创建更多线程以并行化线性搜索会消耗更多时间

  3. 3

    为什么长字面量计算需要更多时间?

  4. 4

    为什么 numpy 数组比列表花费更多时间?

  5. 5

    普通选择查询需要更多时间

  6. 6

    Python多处理需要更多时间

  7. 7

    为什么JSF 2.2需要花费更多时间在Wildfly上部分渲染ajax请求

  8. 8

    为什么Azure ML Studio(经典)需要花费更多时间来执行Python脚本?

  9. 9

    当文件更多时,FTP需要花费更多时间来消耗消息-ESB

  10. 10

    为什么通过主机名执行ping操作比通过IP地址花费更多时间?

  11. 11

    Neo4j插入需要更多时间

  12. 12

    春季休眠需要更多时间的任何原因?

  13. 13

    注销:与同步FileAppender相比,AsyncAppender需要更多时间

  14. 14

    C#需要更多时间进行首次执行

  15. 15

    Neo4j插入需要更多时间

  16. 16

    为什么在启动更多进程时基于Fortran的MPI例程需要更多的计算时间

  17. 17

    为什么在启动更多进程时基于Fortran的MPI例程需要更多的计算时间

  18. 18

    为什么在E_OUTOFMEMORY后跟“无法创建更多线程”?

  19. 19

    为什么开普勒GK107中的更多线程出现较慢的算法?

  20. 20

    尽管使用了更多线程,为什么我的程序变慢了?

  21. 21

    为什么我的 Eigen 代码不能使用更多线程进行缩放

  22. 22

    为什么SOAP比REST需要更多的带宽和更多的资源?

  23. 23

    为什么User.first会花更多时间第一次查询数据库?

  24. 24

    为什么单片内核需要更多的重启?

  25. 25

    为什么wait()函数需要更多参数?

  26. 26

    为什么单片内核需要更多的重启?

  27. 27

    检查 Parallel.Foreach 中的线程所花费的时间,如果花费更多时间则退出

  28. 28

    为什么多线程版本需要与单线程版本相同的时间?

  29. 29

    MSSQL参数消耗更多时间

热门标签

归档