【问题标题】:pthread works fine only if the number of threads is smallpthread 只有在线程数很少时才能正常工作
【发布时间】:2026-02-09 03:20:06
【问题描述】:

我正在尝试逐像素加密 BMP 图像,并使用 pthread 并行加密它们。

我的代码是这样的:

struct arg_struct {
    int arg1;
    int arg2;
    ...
};

void* print_message(void* arguments) {
    struct arg_struct* args = (struct arg_struct*)arguments;

    //Encryption...

    // exit from current thread
    pthread_exit(NULL);
}

void multiThreadExample() {
    cout << "Start..." << endl;
    const int NUMBER_OF_THREADS = 50000; // number of pixels
    pthread_t thread[NUMBER_OF_THREADS];
    arg_struct arg[NUMBER_OF_THREADS];
    for (int i=0;i<NUMBER_OF_THREADS;i++) {
        arg[i].arg1 = i;
        arg[i].arg2 = ... // give values to arguments in arg_struct
        pthread_create(&thread[i], NULL, print_message, static_cast<void*>(&arg[i]));
    }

    for(int i = 0; i < NUMBER_OF_THREADS; i++) {
        pthread_join(thread[i], NULL);
    }

    cout << "Complete..." << endl;

    //streaming results to file using filebuf
}

int main() {

    multiThreadExample();

    return 0;
}

如果图像小到 3*3 就可以了。

如果图像变大,例如 240*164,程序会在 AFTER 打印出“Complete...”时冻结

几分钟后,它显示Segmentation fault (core dumped)

我不确定是什么让程序在最重的部分(加密)已经完成后冻结。是不是因为这么多线程已经占满了我所有的内存空间?运行时最大占用10G以上。


实际上我已经尝试过不使用多线程,但程序仍然冻结。

【问题讨论】:

  • 您需要检查pthread_create 是否成功。 50000 pthreads 是一吨,你不能加入没有成功创建的线程。
  • 我觉得join函数应该成功了吧?因为如果不成功,cout &lt;&lt; "Complete..." &lt;&lt; endl;就不应该被执行。
  • @TaihouKai -- 不要猜测,而是检查那些会在失败时报告错误的函数的返回码。
  • 为什么在 C++ 中使用原始 pthread?我们有std::thread 和朋友。
  • 谷歌搜索两个词然后随机选择两个结果之一是...... 不是如何在计算机编程中做出架构决策。 研究你的选择。

标签: c++ multithreading pthreads


【解决方案1】:

50000 个线程太疯狂了。您很可能会用尽内存来为线程分配堆栈。通常,要通过并行性充分利用 CPU,您只需要与 CPU 内核一样多的线程 - 这是您可以在硬件中获得的实际并发量的限制。再多的线程,你只是在消耗资源来产生线程创建和上下文切换的开销。

相反,创建一个与您拥有的内核数量相等的线程池,并将您的图像分成块,然后将它们调度到您创建的线程上。

【讨论】:

  • 使用超线程,限制为 2*CPU 内核,一些奇特的芯片可以管理更多的线程/内核。但这仍然让你离 50.000 还很远。
  • 当我尝试在没有多线程的情况下加密整个图像(约 40000 像素大)时,程序仍然冻结。我在想是否是因为我在 for 循环中 ~40000 次迭代期间没有分配回一些内存,因此内存不足。很抱歉,我忘记在我的问题中提及这一点。
  • @TaihouKai 听起来是时候 a) 添加错误处理了。 b) 使用您的调试器。 c) 使用“thread sanitizer”和“address sanitizer”等工具。
  • @TaihouKai 或者 d) 提出一个新问题,在哪里显示更多代码;)
  • @TaihouKai and e) 把你的编译器警告调高,把警告变成错误。