搜索

高性能计算的线程模型:Pthreads 还是 OpenMP

gecimao 发表于 2019-06-06 09:05 | 查看: | 回复:

  UNIX 操作系统多年来一直支持线程,这是 UNIX 在服务器系统上异常活跃的主要原因之一。在过去几年间,Linux* 一直宣传自己通过改进线程的内核支持而在服务器上的出色表现。例如,kernel 最近发布的 2.6 版增加了全新的调度程序,能够通过可以在 Linux 系统上切换的线程来大幅度优化速度。kernel 之前的版本(2.4 版--Linux kernel 使用偶数代表发布的版本,奇数代表正在开发的版本)同样根据线程能力的大幅度改进来划分。这些进步有助于将 Linux 放在服务器上和放入支持高性能计算(HPC)的站点中。此外,Linux 放弃其原有的线程 API(称为 Linux 线程)并采用 Pthreads 作为其固有的线程界面,连接目前可用的大部分 UNIX 变量。

  然而,Linux 开发人员(如使用 UNIX 和 Windows* 的程序员)可以使用称为 OpenMP* 的第二种线程 API,这由服务器厂商联盟精心设计而成。本文将 Pthreads 和 OpenMP 进行比较,并尝试确定哪一种能够使开发人员受益最多。

  Pthreads 是 IEEE(电子和电气工程师协会)委员会开发的一组线程接口,负责指定便携式操作系统接口(POSIX)。Pthreads 中的 P 表示 POSIX,实际上,Pthreads 有时候也代表 POSIX 线程。基本上,POSIX 委员会定义了一系列基本功能和数据结构,它希望能够被大量厂商采用,因此线程代码能够轻松地在操作系统上移植。委员会的梦想由 UNIX 厂商实现了,他们都大规模实施 Pthreads。(最著名的例外就是 Sun,它继续采用 Solaris* 线程作为其主要线程 API。)由于 Linux 的采用和移植到 Windows 平台,Pthreads 的可能性一直被进一步扩展。

  Pthreads 指定 API 来处理线程要求的大部分行为。这些行为包括创建和终止线程、等待线程完成、以及管理线程之间的交互。后面的目录中存在各种锁定机制,能够阻止两个线程同时尝试修改相同的数据值:互斥体、条件变量和信号量。(从技术上讲,信号量不是 Pthreads 的一部分,但是它们从概念上更接近于与线程合作,而且可用于 Pthreads 能够运行的所有系统上。)

  为了使用 Pthreads,开发人员必须为这一 API 专门编写代码。这就意味着它们必须包括标头文件、宣布 Pthreads 数据结构、并调用 Pthreads 指定的函数。基本上,此流程与使用其它库没有不同。和 UNIX 以及 Linux 上的其它库一样,Pthreads 库只是简单地链接到应用代码(通过 -lpthread 参数)。

  虽然 Pthreads 库相当复杂(尽管不像一些其它固有的 API 设置那样广泛)而且显然具有便携性,但是全部固有线程 API 常用的严格限制条件也使它非常艰难:它需要大量线程专用代码。换言之,为 Pthreads 进行编码就要在线程模型中建立代码库,这是不可回避的。此外,一些决策(如需要使用的线程数据)也将成为程序中的硬编码。作为这些限制的交换条件,Pthreads 能提供对于线程操作的广泛控制--这是一个固有的低级 API,通常要求多个步骤来执行简单的线程任务。例如,使用线程循环来通过大型数据块需要宣布线程结构、单独创建线程、计算通向每个线程的循环并分配到线程、最终处理线程终止--所有这些必须由开发人员进行编码。如果循环不仅仅是简单的叠代,则线程指定代码的数量将显著增加。为了公平起见,对于如此多代码的需求存在于所有本地线程 API 中,而不仅仅是 Pthreads。

  鉴于需要执行直接操作的线程代码的数量,开发人员一直在寻找更简单的 Pthreads 替代品。

  1997 年,一些厂商携手合作,在硬件制造商 Silicon Graphics 的支持下组成了新的线程接口。他们共同的问题是主要的时间操作系统全部利用了完全不同的线程编程方法。UNIX 使用 Pthreads、Sun 使用 Solaris 线程、Windows 使用自己的 API、而 Linux 则使用 Linux 线程(直到其后来采用 Pthreads)。委员会希望设计出能够支持代码库不需要改变即可在 Windows 和 UNIX/Linux 上平等运行的 API。1998 年,它提供了第一个称为 OpenMP 的 API 规范(在这些日子里,“开放”这个词汇与多厂商支持的概念相关,是指开放系统,而不是现在的开放源代码的含义。)

  OpenMP 规范包括 API、一组编译指示、以及对 OpenMP 指定环境变量的几种设置。随着对标准的进一步修订,OpenMP 最实用的特性之一就是那一组编译指示,这一点逐渐明朗。通过明智地使用这些编译指示,单线程程序不需要向 API 或环境变量求助即可实现多线程。通过 OpenMP 2.0 的最新版本,OpenMP 架构审核委员会(ARB)是提出 OpenMP 规范的委员会的正式名称,显然开发人员使用编译指示而不是 API 作为优先选择。让我们来更深入地审视这种方法,从翻新编译指示开始。

  以下关于编译指示的定义(摘自微软的文档)是最清晰的解释之一:“#pragma 指示为每个编译器提供了一种方法,能够提供机器指定和操作系统指定特性,同时保留与 C 和 C++ 语言的整体兼容性。根据定义,编译指示是机器指定或操作系统指定的,通常所有的编译器都不同。编译指示最常用于 C 和 C++ 中,格式如下:#pragma token-string”

  编译指示的主要方面是如果编译器不能识别指定的编译指示,则它必须忽略(根据 ANSI C 和 C++ 标准)。因此,将库指定的编译指示放入代码中是安全的,不需要担心如果采用不同的工具包进行编译会将代码破坏。

  这种编译指示告诉编译器:以后的for 循环应该实现多线程化,而且线程应该并行执行。简单的解释就是:在编译器完成的工作与 OpenMP 库之间,for 循环将使用大量线程来执行。OpenMP 将致力于创建线程、通过在线程间划分交互作用来实现 for 循环的线程化、以及在 for 循环完成后处理线程。

  虽然 OpenMP 不保证推理将创建多少线程,但是它通常选择等于可用执行管线数量的数量。在标准多处理器环境中,这一数量就是处理器的数量。在采用含超线程(HT)技术的处理器的系统上,管线的数量是处理器数量的两倍。API 函数或环境变量可用于撤销默认的线程数量。

  OpenMP 将提供大量其它的编译指示来识别需要进行线程化的代码块、在线程中共享的范围变量或本地化到单独线程,到同步线程,如何安排任务或循环叠代到线程,等等。因此,最终它将通过线程功能提供中等级别纹理型控制。这种级别的纹理对于许多高性能计算(HPC)应用而言已经足够,在便携性和最佳执行能力的前提下,OpenMP 能够提供比大多数其它选择更好的选择,尤其是最大限度减少对于代码库的干扰。

  OpenMP 非常方便,因为它不会将软件锁定在事先设定的线程数量中。此类锁定工作给使用低级 API(如 Pthreads 或 Win32)的线程应用提出了一个大问题。当运行在更多处理器可用的平台上时,使用这些 API 编写的软件如何扩充线程的数量?一种方法一直是使用线程池(threading pool),其中在程序启动时创建一束线程,将工作分配到线程上。然而,这种方法需要相当多的线程指定代码,而且不能保证能够随着可用处理器的数量而合理地进行扩充。通过 OpenMP,不需要指定数量。

  OpenMP 的编译指示还有另一项重要优势:通过禁用 OpenMP 支持,代码可用作为单一线程应用进行编译。当调试程序时,以这样的方式编译代码拥有巨大优势。如果没有这种选择,开发人员会经常发现很难说明复杂的代码是否能够正确工作,因为线程问题或因为与线程无关的设计错误。

  如果开发人员需要精细纹理的控制,则他们可以使用 OpenMP 的线程 API。其中包括一小组函数,分为以下三个领域:查询执行环境的线程资源并设置当前的线程数量;设置、管理并释放锁来解决线程之间的资源访问;和一个小型的定时接口。使用这种 API 让人失望,因为它会取走纯编译指令方法提供的优势。在这个级别上,OpenMP API 是 Pthreads 提供的功能的一个小子集。这两个 API 都具有便携性,但是 Pthreads 能提供更大范围的原函数(primitive function),从而对线程化操作提供精细纹理的控制。因此,在必须单独管理线程的应用中,Pthreads 或本地的线程化 API(如 Windows 上的 Win32)将是更加自然的选择。

  因此,如果您正在为高性能计算(HPC)编写 UNIX 或 Linux 应用,则应该关注 Pthreads 和 OpenMP。您可能会发现 OpenMP 是一款不错的解决方案。

  关于高性能计算的知识记录汇总   原文来自:看了这个文章,对我的知识面有了很大的补充,感谢...博文来自:楷尘·极客

  PHP5.3以上版本使用pthreadsPHP扩展真正支持多线以上版本,使用pthreadsPHP扩展,可以使PHP真正地支持多线程。多线程在处理重复性的循环任务,能够大大缩短程序执行时间。我之前的文章中说过,大多数网站的性能瓶颈不在PHP服务器上,...

  Java线程模型、线.概述众所周知,线程-Thread是比进程-Progress更轻量级的调度单位。简单来说,引入线程带来的好处是:可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址、文件I/...

  大数据的概念太大太宽泛了,感觉跟物联网有些类似。谁都可以说自己是做大数据的,谁都觉得自己是在做物联网。本着务实的心态,还得看看本质。个人感觉如果单纯用着工具,无论是什么,都不能认为自己技术NB了。过几...博文

  这篇文章主要介绍了PHP使用Pthread实现的多线程操作的方法,以完整实例形式分析了php多线程的创建及使用相关技巧,需要的朋友可以参考下...博文来自:这样的霍少楠

  简介:pthreads是一组允许用户在PHP中使用多线程技术的面向对象的API。它提供了创建多线程应用所需的全套工具,无论是Web应用还是控制台应用。通过使用Thread,Worker以及Thread...博文来自:P_Leung的技术博客

  最近好长时间都没有写blog了,主要是因为最近工作上的事以及下载Android源码的事耽误的(下载源码这件事会在后续的blog中写道,这个真的很有意义呀~~),那么今天来写点什么呢?主要的灵感来自于早...

  为什么会有这个问题我不懂,造成这个问题的原因可能有很多。我也不清楚在我电脑上造成这个问题的原因是什么,所以这里的方法是我偶然尝试所得,只是可供参考的方法之一,不保证一定有效。一句话,解决方法就是停掉虚...

  原文链接:一、Layer的作用简介 Layer实际上定义了Layer的基本操作,即...博文来自:

  学事件分发是为了什么呢?还不是为了解决滑动冲突的。 实际上,如果仅仅是为了解决滑动冲突的,大可不必看源码,只需要掌握事件分发的外在规律即可。 只要记住这张图,再明白内部拦截法和外部拦截法,滑动冲突...博文来自:

  nginx是个好东西,Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambl...博文来自:

  最近比较有空,大四出来实习几个月了,作为实习狗的我,被叫去研究Docker了,汗汗! Docker的三大核心概念:镜像、容器、仓库 镜像:类似虚拟机的镜像、用俗话说就是安装文件。 容器:类似一个轻量...博文来自:

  Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的Thread...博文来自:

  实际上关于数组与指针的区别这个问题在《C专家编程》已经有很详细的阐释,但我想用自己的语言说一说我的理解。数组是指针?最近在做数据结构课设,其中一个函数发生了令人费解的错误,简化后的代码如下:#incl...博文来自:

  采用EasyUI 1.4.x 版本,默认default风格,异步加载页面,多Tab页展示,使用JSON文件模拟从后台动态获取数据。...博文来自:

  扫二维码关注,获取更多技术分享 本文承接之前发布的博客《 微信支付V3微信公众号支付PHP教程/thinkPHP5公众号支付》必须阅读上篇文章后才可以阅读这篇文章。由于最近一段时间工作比较忙,...博文来自:

  在网上所搜索很多操作Word的都是用VC,VS2010做了一些修改,添加操作的方式和用法都有所变化。 要操作Word必须先添加对应的类,如下图在工程中添加操作类(TypeLib中的 MFC类): ...博文来自:

  jquery/js实现一个网页同时调用多个倒计时(最新的)11-25阅读数 52万+

本文链接:http://windsorflowers.net/dijihuchi/267.html
随机为您推荐歌词

联系我们 | 关于我们 | 网友投稿 | 版权声明 | 广告服务 | 站点统计 | 网站地图

版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright @ 2012-2013 织梦猫 版权所有  Powered by Dedecms 5.7
渝ICP备10013703号  

回顶部