pthreads 与 GCD 相比有什么优势吗?

发布于 2024-08-19 15:43:43 字数 436 浏览 2 评论 0原文

最近学习了 Grand Central Dispatch,我发现多线程代码非常直观(使用 GCD)。我喜欢这样的事实:不需要锁(并且它内部使用无锁数据结构),并且 API 非常简单。

现在,我开始学习 pthreads,我不禁对它的复杂性感到有点不知所措。线程连接、互斥体、条件变量——所有这些东西在 GCD 中都不是必需的,但在 pthread 中有很多 API 调用。

pthreads 与 GCD 相比有什么优势吗?是不是更有效率?在正常使用情况下,pthreads 是否可以做 GCD 不能做的事情(不包括内核级软件)?

至于跨平台兼容性,我不太关心。毕竟,libdispatch 是开源的,Apple 已将其闭包更改作为 GCC 补丁提交,clang 支持闭包,并且已经(前 FreeBSD)我们开始看到一些 GCD 的非 Apple 实现。我最感兴趣的是 API 的使用(具体的例子就太好了!)。

Having recently learned Grand Central Dispatch, I've found multithreaded code to be pretty intuitive(with GCD). I like the fact that no locks are required(and the fact that it uses lockless data structures internally), and that the API is very simple.

Now, I'm beginning to learn pthreads, and I can't help but be a little overwhelmed with the complexity. Thread joins, mutexes, condition variables- all of these things aren't necessary in GCD, but have a lot of API calls in pthreads.

Does pthreads provide any advantages over GCD? Is it more efficient? Are there normal-use cases where pthreads can do things that GCD can not do(excluding kernel-level software)?

In terms of cross-platform compatibility, I'm not too concerned. After all, libdispatch is open source, Apple has submtited their closure changes as patches to GCC, clang supports closures, and already(e.x. FreeBSD), we're starting to see some non-Apple implementations of GCD. I'm mostly interested in use of the API(specific examples would be great!).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

千纸鹤带着心事 2024-08-26 15:43:44

与任何声明性/辅助方法一样,例如 openmp英特尔 TBB GCD 应该非常擅长令人尴尬的并行 a> 问题,并且可能会轻松击败天真的手动 pthread 并行排序。不过我建议你仍然学习 pthreads。您将更好地理解并发性,您将能够在每种特定情况下应用正确的工具,并且如果没有其他事情 - 那里有大量基于 pthread 的代码 - 您将能够阅读“遗留”代码。

As any declarative/assisted approach like openmp or Intel TBB GCD should be very good at embarrassingly parallel problems and will probably easily beat naïve manually pthread-ed parallel sort. I would suggest you still learn pthreads though. You'll understand concurrency better, you'd be able to apply right tool in each particular situation, and if for nothing else - there's ton of pthread-based code out there - you'd be able to read "legacy" code.

七颜 2024-08-26 15:43:44

通常:每个 Pthread 实现有 1 个任务使用互斥体(操作系统功能)。
全局CD:
每个块 1 个任务,分组到队列中。每个虚拟 CPU 1 个线程可以获得一个队列,并在没有互斥锁的情况下运行所有​​任务。这减少了线程管理开销和互斥开销,从而提高性能。

Usual: 1 task per Pthread implementations use mutexes (an OS feature).
GCD:
1 task per block, grouped into queues. 1 thread per virtual CPU can get a queue and run without mutexes through all the tasks. This reduces thread management overhead and mutex overhead, which should increase performance.

神也荒唐 2024-08-26 15:43:44

GCD 抽象线程并为您提供调度队列。它会根据可用处理器核心的数量来创建它认为必要的线程。
GCD 是开源的,可以通过 libdispatch 库获得。 FreeBSD 从 8.1 开始包含 libdispatch。 GCD 和 C Blocks 是 Apple 对 C 编程社区的重大贡献。我永远不会使用任何不支持 GCD 的操作系统。

GCD abstracts threads and gives you dispatch queues. It creates threads as it deems necessary taking into account the number of processor cores available.
GCD is Open Source and is available through the libdispatch library. FreeBSD includes libdispatch as of 8.1. GCD and C Blocks are mayor contributions from Apple to the C programming community. I would never use any OS that doesn't support GCD.

一个人的旅程 2024-08-26 15:43:43

我来自另一个方向:开始在我的应用程序中使用 pthreads,最近我用 C++11 的 std::thread 替换了它。现在,我正在尝试更高级别的构造,例如 pseudo-boost 线程池,甚至更抽象的是英特尔的 线程构建块。我认为GCD等于甚至高于TBB。

一些评论:

  • 恕我直言,pthread 比 GCD 不复杂:在其基本核心,pthread 实际上包含很少的命令(只有少数:仅使用 OP 中提到的命令将为您提供 95% + 您需要的功能)。与任何较低级别的库一样,如何将它们组合在一起以及如何使用它才赋予它力量。不要忘记,最终,像 GCD 和 TBB 这样的库将调用像 pthreadsstd::thread 这样的线程库。
  • 有时,决定成功与失败的不是你使用什么,而是你如何使用它。作为库的支持者,TBB 或 GCD 会告诉您使用他们的库的所有好处,但在您在实际应用程序环境中尝试它们之前,所有这些都只是理论上的好处。例如,当我了解到使用细粒度的parallel_for是多么容易时,我立即将其用于我认为可以从并行性中受益的任务中。当然,我也被 TBB 会处理有关最佳负载平衡和线程分配的所有细节所吸引。结果呢? TBB 花费的时间是单线程版本的五倍!但我并不责怪 TBB:回想起来,这显然是滥用 parallel_for 的情况:当我阅读细则时,我发现了使用parallel_for 所涉及的开销,并假设在我的例子中,上下文切换和添加函数调用的成本超过了使用多线程的好处。因此,您必须分析您的案例,看看哪一个运行得更快。您可能必须重新组织算法以使用更少的线程开销。
  • 为什么会发生这种情况? pthread 或无线程如何比 GCD 或 TBB 更快?当设计者设计 GCD 或 TBB 时,他必须对任务运行的环境做出假设。事实上,该库必须足够通用,能够处理开发人员奇怪的、不可预见的用例。这些一般性的实现并不是免费的。从好的方面来说,库将查询硬件和当前的运行环境,以更好地进行负载平衡。它会对您有利吗?唯一知道的方法就是尝试一下。
  • 当有更高级别的库可用时,学习像 std::thread 这样的低级别库有什么好处吗?答案是响亮的是。使用高级库的优点是,从实现细节中抽象。使用高级库的缺点还在于从实现细节中抽象。当使用pthreads时,我非常清楚对象的共享状态和生命周期,因为如果我放松警惕,特别是在中型到大型项目中,我可以很容易地得到竞争条件或内存故障。当我使用更高级别的库时,这些问题会消失吗?并不真地。看起来我不需要考虑它们,但事实上,如果我对这些细节马虎,库的实现也会崩溃。因此,您会发现,如果您了解较低级别的构造,所有这些库实际上都是有意义的,因为在某些时候,如果您使用较低级别的调用,您将考虑自己实现它们。当然,此时,通常最好使用经过时间测试和调试的库调用。

因此,让我们分解一下可能的实现:

  • TBB/GCD 库调用:最大的好处是对于线程初学者。与学习较低级别的图书馆相比,它们的进入门槛较低。然而,它们也忽略/隐藏了一些使用多线程的陷阱。动态负载平衡将使您的应用程序更加可移植,而无需您进行额外的编码。
  • pthreadstd::thread 调用:实际上需要学习的调用很少,但正确使用它们需要注意细节并深入了解应用程序的工作原理。如果你能理解这个级别的线程,那么更高级别的库的 API 肯定会更有意义。
  • 单线程算法:我们不要忘记简单的单线程段的好处。对于大多数应用程序来说,单线程比多线程更容易理解并且更不容易出错。事实上,在很多情况下,这可能是合适的设计选择。事实是,真实的应用程序会经历各种多线程阶段和单线程阶段:可能不需要一直是多线程的。

哪一个最快?令人惊讶的事实是,它可能是上述三个中的任何一个。为了获得多线程的速度优势,您可能需要彻底重新组织您的算法。收益是否大于成本很大程度上取决于具体情况。

哦,OP 询问了 thread_pool 不合适的情况。简单的情况:如果您有一个紧密的循环,每个循环不需要很多周期来计算,那么使用 thread_pool 的成本可能会超过其收益,而无需进行认真的返工。还要注意通过线程池进行 lambda 等函数调用与使用单个紧密循环的开销。

对于大多数应用程序来说,多线程是一种优化,所以要在正确的时间、正确的地方进行。

I am coming from the other direction: started using pthreads in my application, which I recently replaced with C++11's std::thread. Now, I am playing with higher-level constructs like the pseudo-boost threadpool, and even more abstract, Intel's Threading Building Blocks. I would consider GCD to be at or even higher than TBB.

A few comments:

  • imho, pthread is not more complex than GCD: at its basic core, pthread actually contains very few commands (just a handful: using just the ones mentioned in the OP will give you 95%+ of the functionality that you ever need). Like any lower-level library, it's how you put them together and how you use it which gives you its power. Don't forget that the ultimately, libraries like GCD and TBB will call a threading library like pthreads or std::thread.
  • sometimes, it's not what you use, but how you use it, which determines success vs failure. As proponents of the library, TBB or GCD will tell you about all the benefits of using their libraries, but until you try them out in a real application context, all of it is of theoretical benefit. For example, when I read about how easy it was to use a finely-grained parallel_for, I immediately used it in a task for which I thought could benefit from parallelism. Naturally, I, too, was drawn by the fact that TBB would handle all the details about optimal loading balancing and thread allocation. The result? TBB took five times longer than the single-threaded version! But I do not blame TBB: in retrospect, this is obviously a case of a misuse of the parallel_for: when I read the fine-print, I discovered the overhead involved in using parallel_for and posited that in my case, the costs of context-switching and added function calls outweighed the benefits of using multiple threads. So you must profile your case to see which one will run faster. You may have to reorganize your algorithm to use less threading overhead.
  • why does this happen? How can pthread or no threads be faster than a GCD or a TBB? When a designer designs GCD or TBB, he must make assumptions about the environment in which tasks will run. In fact, the library must be general enough that it can handle strange, unforseen use-cases by the developer. These general implementations will not come for free. On the plus-side, a library will query the hardware and the current running environment to do a better job of load-balancing. Will it work to your benefit? The only way to know is to try it out.
  • is there any benefit to learning lower-level libraries like std::thread when higher-level libraries are available? The answer is a resounding YES. The advantage of using higher-level libraries is, abstraction from the implementation details. The disadvantage of using higher-level libraries is also abstraction from the implementation details. When using pthreads, I am supremely aware of shared state and lifetimes of objects, because if I let my guard down, especially in a medium to large size project, I can very easily get race conditions or memory faults. Do these problems go away when I use a higher-level library? Not really. It seems like I don't need to think about them, but in fact, if I get sloppy with those details, the library implementation will also crash. So you will find that if you understand the lower-level constructs, all those libraries actually make sense, because at some point, you will be thinking about implementing them yourself, if you use the lower-level calls. Of course, at that point, it's usually better to use a time-tested and debugged library call.

So, let's break down the possible implementations:

  • TBB/GCD library calls: greatest benefit is for beginners of threading. They have lower barriers to entry compared to learning lower level libraries. However, they also ignore/hide some of the traps of using multi-threading. Dynamic load balancing will make your application more portable without additional coding on your part.
  • pthread and std::thread calls: there are actually very few calls to learn, but to use them correctly takes attention to detail and deep awareness of how your application works. If you can understand threads at this level, the APIs of higher-level libraries will certainly make more sense.
  • single-threaded algorithm: let us not forget the benefits of a simple single-threaded segment. For most applications, a single-thread is easier to understand and much less error-prone than multi-threading. In fact, in many cases, it may be the appropriate design choice. The fact of the matter is, a real application goes through various multi-threading phases and single-threading phases: there may be no need to be multi-threaded all the time.

Which one is fastest? The surprising truth is, it could be any of the three of the above. To get speed benefits of multi-threading, you may need to drastically reorganize your algorithms. Whether or not the benefits outweigh the costs is highly case-dependent.

Oh, and the OP asked about cases where a thread_pool is not appropriate. Easy case: if you have a tight loop that does not require many cycles per loop to compute, using thread_pool may cost more than the benefits without serious reworking. Also be aware of the overhead of function calls like lambda through thread pools vs the use of a single tight loop.

For most applications, multi-threading is a kind of optimization, so do it at the right time and in the right places.

你好,陌生人 2024-08-26 15:43:43

你正在经历的那种压倒性的感觉......这正是 GCD 被发明的原因。

在最基本的层面上有线程,pthreads 是线程的 POSIX API,因此您可以在任何兼容的操作系统中编写代码并期望它能够工作。 GCD 构建在线程之上(尽管我不确定他们是否真的使用 pthreads 作为 API)。我相信 GCD 只能在 OS X 和 iOS 上运行——简而言之,这是它的主要缺点。

请注意,大量使用线程并需要高性能的项目会实现自己的线程池版本。 GCD 可以让您避免无数次(重新)发明轮子。

That overwhelming feeling that you are experiencing.. that's exactly why GCD was invented.

At the most basic level there are threads, pthreads is a POSIX API for threads so you can write code in any compliant OS and expect it to work. GCD is built on top of threads (although I'm not sure if they actually used pthreads as the API). I believe GCD only works on OS X and iOS — that in a nutshell is its main disadvantage.

Note that projects that make heavy use of threads and require high performance implement their own version of thread pools. GCD allows you to avoid (re)inventing the wheel for the umpteenth time.

若相惜即相离 2024-08-26 15:43:43

GCD是Apple技术,并不是最跨平台兼容的; pthread 几乎可以在 OSX、Linux、Unix、Windows 等所有平台上使用,包括 toaster

GCD 针对线程池并行性进行了优化。 Pthreads(正如您所说)是非常复杂的并行构建块,您只能开发自己的模型。如果您有兴趣了解有关 pthread 和不同并行模型的更多信息,我强烈建议您阅读一本有关该主题的书。

GCD is an Apple technology, and not the most cross platform compatible; pthread are available on just about everything from OSX, Linux, Unix, Windows.. including this toaster

GCD is optimized for thread pool parallelism. Pthreads are (as you said) very complex building blocks for parallelism, you are left to develop your own models. I highly recommend picking up a book on the topic if you're interested in learning more about pthreads and different models of parallelism.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文