【问题标题】:C++ Pthreads - Multithreading slower than single-threading [closed]C ++ Pthreads - 多线程比单线程慢[关闭]
【发布时间】:2015-02-10 15:53:51
【问题描述】:

我正在使用 pthreads 库开发 C++ 应用程序。程序中的每个线程都访问一个公共的 unordered_map。该程序在 4 个线程下比 1 个运行得慢。我在线程中注释了所有代码,只留下了标记字符串的部分。单线程执行仍然更快,所以我得出的结论是映射不是问题。 之后,我将线程的 ID 打印到屏幕上,它们似乎是按顺序执行的。

在调用线程的函数中,我有一个 while 循环,它在一个数组中创建线程,其大小是线程数(假设是“tn”)。每次创建 tn 线程时,我都会执行一个 for 循环来加入它们。 (pthread_join)。虽然运行了很多次(不仅是 4 次)。

可能出了什么问题?

【问题讨论】:

  • 您是否使用互斥锁来访问地图?
  • 我的魔法 8-ball 说错误在第 42 行。[即,根据对代码可能或不可能做的部分的高级描述,甚至无法猜测。]跨度>
  • 慢多少?您是否使用可以从多线程中受益的架构?
  • @user3309479 你应该在问题中提到这一点。我是相关的。
  • 但是当我删除关键部分并只保留标记时,它仍然较慢。还是标记化微不足道?

标签: c++ multithreading performance pthreads posix


【解决方案1】:

如果您正在运行一个小型的琐碎程序,这往往是这种情况,因为启动线程、调度优先级、运行、上下文切换的工作,然后同步实际上可能比作为单个进程运行它需要更多的时间。

这里的重点是,在处理琐碎的问题时,它可能会运行得更慢。但另一个因素可能是您的 CPU 中实际有多少内核。

【讨论】:

  • 每个线程都将一个非常大的文本作为参数。它对其进行标记并将其单词添加到地图中。该线程创建一个临时映射。然后当它完成标记化时,它将临时映射添加到公共映射中。我有4个核心。时间乘以~4。但我试图删除关于地图的代码并只保留标记化..但仍然
  • @user3309479 你忘了在问题中提到这一点。
  • @user2079303:并且该映射必须与互斥锁同步,以便一次只有一个线程可以使用它。因此,您的代码是序列化的,线程对您没有帮助。
  • 是的,当我写入公共映射时,我正在使用互斥锁。
【解决方案2】:

当您运行多线程程序时,每个线程将根据给定的 CPU 时钟顺序处理。

如果您有多个内核,您将只有真正的多线程。在这种情况下,唯一的多线程将是 1 个线程/核心。

现在,考虑到您(很可能)在一个内核上同时拥有两个线程,请尽量记住对 CPU 产生的开销:

  • 为每个线程分配不同的时钟时间
  • 同步线程访问各种内部 CPU 操作
  • 其他线程优先级操作

所以换句话说,对于一个简单的应用程序来说,多线程在性能方面实际上是一种降级。

当您需要异步操作时,多线程会派上用场(这意味着您不想等待结果,例如从 url 加载图像或从比 ram 慢的 HDD 流式传输几何图形)。

在这种情况下,应用多线程会带来更好的用户体验,因为你的程序不会在出现慢操作时挂起。

【讨论】:

  • 这个答案对我来说似乎有点过时了。现在的大多数系统都有多个内核。
  • 你可以考虑这个。但是,如果你的线程数多于内核数,你就会遇到同样的问题。更重要的是,大多数操作系统运行多个进程,每个进程都有自己的线程系统。难免会在一个 CPU 上遇到多个线程的问题,从而导致每个线程按照优先级分配 CPU 时钟。
【解决方案3】:

没有看到代码很难确定,但可能存在许多问题。

您的线程可能没有做足够的工作来证明它们的创建是正确的。创建和运行线程的成本很高,所以如果你的工作量太小,它们就不会为自己买单。

执行时间可能主要用于在映射上进行内存访问,在这种情况下,相互排除线程意味着您实际上并没有真正做很多并行工作(阿姆达尔定律)。

【讨论】:

    【解决方案4】:

    如果您的大部分代码在互斥锁下运行,它将串行运行而不是并行运行

    【讨论】:

      猜你喜欢
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多