【问题标题】:Why am I not seeing any speedup from the multithreading in this program?为什么我在这个程序中没有看到多线程的任何加速?
【发布时间】:2017-06-13 14:41:13
【问题描述】:

我有这个功能。它递归地计算曲线下的竞技场。它在具有两个内核的计算机上运行。

void* quad(void* argis){
    struct args* arg=argis;

    double m=(arg->l+arg->r)/2;
    double fm=func(m);
    double larea=(arg->fl+fm)*(m-arg->l)/2;
    double rarea = (fm+arg->fr)*(arg->r-m)/2;

    struct args* arg1 = (struct args*)malloc(sizeof(struct args));
    arg1->l=arg->l;
    arg1->r=m;
    arg1->fl=arg->fl;
    arg1->fr=fm;
    arg1->area=larea;

    struct args* arg2 = (struct args*)malloc(sizeof(struct args));
    arg2->l=m;
    arg2->r=arg->r;
    arg2->fl=fm;
    arg2->fr=arg->fl;
    arg2->area=rarea;

    if(fabs((larea+rarea)-arg->area)>error){
        if(threads<=1){
            void* p1=quad(arg1);
            void* p2=quad(arg2);
            larea=*((double*)p1);
            rarea=*((double*)p2);
            free(p1);
            free(p2);


        }
        else{
            pthread_t thread1, thread2;
            pthread_mutex_lock(&lock1);
            threads-=2;
            pthread_mutex_unlock(&lock1);

            pthread_create(&thread1, NULL, &quad, (void*)arg1);
            pthread_create(&thread2, NULL, &quad, (void*)arg2);

            void* ptr1;
            void* ptr2;

            pthread_join(thread1,&ptr1);
            pthread_join(thread2,&ptr2);


            larea=*(double*)ptr1;
            rarea=*(double*)ptr2;

        }
    }
    free(arg1);
    free(arg2);

    double ret= (larea+rarea);
    double* poin=(double*)malloc(sizeof(double));
    *poin=ret;

    return poin;
}

现在,当我将 threads 变量设置为 2 时,它应该创建两个同时执行递归的新线程,我认为这就是这样做的,我对 Pi 有一个合理的估计,但它并不比运行更快在一个线程上(将 threads 设置为 1),实际上它有点慢。

为什么不是两倍快?任何帮助解决这个问题将不胜感激。谢谢。

【问题讨论】:

  • 为什么你认为分割成线程会加速你的代码?你如何进行基准测试?哪个平台? minimal reproducible example 在哪里?哦,不要在 C 中转换 void *
  • 编程很难。
  • 从多个线程对共享对象的非只读、非原子、非同步访问的未定义行为。
  • 不太明白。哪个对象是共享的并且需要同步?
  • @JohnWu:看看if(threads&lt;=1)pthread_mutex_lock(&amp;lock1); threads-=2; pthread_mutex_unlock(&amp;lock1);threads 在一种情况下被访问而没有获取锁,因此锁不会阻止竞争。

标签: c multithreading performance debugging pthreads


【解决方案1】:

您的处理器可能有多个内核,但您的floating point coprocessor 呢?它可能不会,并且会在另一个线程执行 FPU 计算时阻塞每个线程。

另外,请参阅这篇文章:

从同时多线程处理中获益不多的工作负载是大多数单个软件线程使用处理器或内存中的大量资源的工作负载。例如,浮点密集型工作负载可能从同时多线程中获得的收益很少,并且最有可能损失性能。这些工作负载大量使用浮点单元或内存带宽。具有低 CPI 和低缓存未命中率的工作负载可能会看到一些小的好处。

Source

【讨论】:

  • 您的链接有一张很好的“An Intel 80287”图片,但现在不是每个内核都有自己的 FPU 吗?
  • 认为这取决于核心,不是吗?如果只有 OP 提供了该信息。
  • 代码中有许多其他问题非常更有可能导致此问题。请注意,您提供的引用是关于 SMT 的,如果 OP 问题中的“两个核心”是物理核心而不是逻辑核心,这甚至根本不适用。
  • 也许吧。写一个答案并列出问题,我们可以讨论。
  • @JohnWu:我已经在对问题本身的评论中指出了未定义的行为。没有必要争论表现出未定义行为的代码的性能。
【解决方案2】:

这对于多线程来说是一个足够大的问题吗?也许创建新线程和管理锁的开销比用单线程解决问题的成本要大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 2023-03-07
    相关资源
    最近更新 更多