作为操作系统课程的一部分,我正在练习多线程程序,并编写了一个非常基本的程序,计算从1到n的和.然而,当我在我的英特尔i5 1035G7笔记本电脑上运行它时,它比我的台式机Ryzen 5 5600G运行得更快,后者应该比我的笔记本电脑强大得多.串行版(只是在没有多线程的情况下将1加到n)在我的PC上运行得更快,所以我真的很困惑为什么多线程版不能.有人能解释一下为什么吗?任何帮助都将不胜感激.

以下是我的程序的基本 struct :


struct threadData
{
    unsigned long long *tempResult;
    long long start;
    long long end;
};

void *calculateTotal(void *arg)
{
    struct threadData *structPtr = (struct threadData *)arg;
    for (long long i = structPtr->start; i <= structPtr->end; i++)
    {
        *(structPtr->tempResult) += i;
    }
    pthread_exit(0);
}

int main(int argc, char *argv[])
{
    ...
    int numThreads = atoi(argv[1]);
    long long input = atoll(argv[2]);
    struct threadData threadDataArray[numThreads];
    unsigned long long result = 0;
    unsigned long long threadResult[numThreads];
    ...
    pthread_t threads[numThreads];

    for (int i = 0; i < numThreads; i++)
    {
        threadDataArray[i].start = i * input / (numThreads) + 1;
        threadDataArray[i].end = (i + 1) * input / (numThreads);
        threadDataArray[i].tempResult = &threadResult[i];
        int threadCreate = pthread_create(&threads[i], NULL, calculateTotal, (void *)&threadDataArray[i]);
        ...
    }
    // wait for all threads to join
    for (int i = 0; i < numThreads; i++)
    {
        int threadJoin = pthread_join(threads[i], NULL);
        ...
    }
    // calculate total
    for (int i = 0; i < numThreads; i++)
    {
        result += threadResult[i];
    }
    printf("(running in parallel)\nsum is: %llu\n", result);
}

我的笔记本电脑上的结果是:

$ time ./ex2parallel 10 4897582469
(running in parallel)
sum is: 11993157022776859215

real    0m9.955s
user    1m0.628s
sys     0m0.010s

我桌面上的结果是:

$ time ./ex2parallel 10 4897582469
(running in parallel)
sum is: 11993157022776859215

real    0m31.003s
user    4m1.410s
sys     0m0.011s 

我在我的笔记本电脑和台式机上都运行了这两个程序,并希望我的Ryzen台式机运行得比我的笔记本电脑好得多.

推荐答案

虚假分享. 如果更改这些行:


    unsigned long long threadResult[numThreads];

        threadDataArray[i].tempResult = &threadResult[i];

成为


    unsigned long long threadResult[numThreads*8];

        threadDataArray[i].tempResult = &threadResult[i*8];

然后重新运行你的结果,我预计你会发现这两台机器的运行速度都要快得多,而且你的台式机很可能会超过你的笔记本电脑.

您的值threadResults[n]在内存中是相邻的,并且可由笔记本电脑上的6个CPU和台式机上的8个CPU同时访问.这会导致负伸缩--添加的CPU越多,速度就越慢. 通过将它们分开8*sizeof(Long Long),它们可能会在不同的缓存线上移位,或者至少更少的CPU正在敲打相同的CPU.

C++相关问答推荐

如何在不修改字符串缓冲区早期使用的情况下覆盖字符串缓冲区

为什么已经设置的值在C中被重置为for循环条件中的新值?

为什么下面的递归基本情况在C中不起作用?

当输入负数时,排序算法存在问题

如何将字符**传递给需要常量字符指针的常量数组的函数

GDB输出ARM助记符

为什么中断函数会以这种方式影响数组?

在另一个函数中使用realloc和指针指向指针

为什么Fread()函数会读取内容,然后光标会跳到随机位置?

类型定义 struct 与简单的类型定义 struct

循环中的静态变量与块中的变量和循环

如何在不使用字符串的情况下在c中编写函数atof().h>;

C:如何将此代码转换为与数组一起使用?

C";中的ANN运行时判断失败#2-变量outputLayer;周围的堆栈已损坏.运行后出错

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

为什么这个代码的最后一次迭代不能正常工作?

关于不同C编译器中的__attribute__支持

struct 中的qsort,但排序后的 struct 很乱

C循环条件内的函数

使用复合文字数组初始化的指针数组