- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
高性能计算导课件第五章PPT
简单的方法 将输入文件分成行,把每一行按顺序分给线程 即,第一行给线程0,第二行给线程1,…,第t行给线程t-1,第t+1行给线程0,以此类推。 简单的方法 我们可以通过使用信号量将访问输入行串行化 在一个线程读了一行输入后,他就能够对这一行进行分词,使用string.h中的strtok函数 strtok函数 在第一次调用它时,string参数应该是要被分词的文本,在我们的例子中就是一行输入 后面调用它时, string参数应该是NULL strtok函数 在第一次调用时,strtok缓存一个指向string的指针,在接下来连续的调用中,strtok返回从缓存的副本中分隔出的连续的词。 多线程分词器的第一个版本的程序(1) 多线程分词器的第一个版本的程序(2) 用一个线程运行 它能正确地对输入进行分词 Pease porridge hot. Pease porridge cold. Pease porridge in the pot Nine days old. 用两个线程运行 Oops! 这是怎么回事? 再回头看一下strtok如何对输入行进行缓存。它通过声明一个storge类的静态变量来实现对输入行的缓存。 导致从本次调用到下次调用之间,存储在这个变量中的值会一直被保留。 但不幸的是,这个缓存的字符串是共享的,而不是私有的。因此,线程0调用strtok对输入的第3行进行缓存,覆盖了原来线程1调用strtok读入输入的第2行的缓存。 strtok函数不是线程安全的:如果多个线程同时调它,输出可能是不正确的。 其他不安全的C语言的库函数 对于C语言的库函数来说,线程不安全是常见的。 例如,stdlib.h中的随机数生成器random和time.h中的时间转换函数localtime都不是线程安全的。 在某些情况下,C标准库指定一个替代的、线程安全的函数版本 线程安全的函数 strtok有一个线程安全的版本: “_r”表示函数是可重入的,“可重入”有时用做线程安全的同义词。 函数的前两个参数与strtok是一样的。strtok_r使用添加_p的saveptr参数跟踪函数在输入字符串中的位置,它起到strtok函数中缓存指针的作用。 正确的分词程序 通过用strtok_r替代strtok,可以更正原来的Tokenize函数。 只需要简单地声明一个char*变量并传入函数strtok_r的第三个参数,分别用下列调用取代原来程序中的第17行和第20行: 练习 用OpenMP编写完整的线程安全的并行分词程序 提示: 小结 OpenMP是一个共享内存系统上的编程标准,它使用专门的函数和预处理器指令pragmas,所以与Pthreads和MPI不同,OpenMP需要编译器的支持。OpenMP最重要的特色之一就是它的设计使程序员可以逐步并行化已有的串行程序,而不是从零开始编写并行程序。 OpenMP程序使用多线程而不是多进程。线程比进程更加轻量级,除了拥有自己的栈和程序计数器外,同一个进程的线程可以共享该进程几乎所有的资源。 为了使用OpenMP中的函数和宏,需要将omp.h头文件包含在OpenMP程序中。有几个OpenMP指令可以开启多线程,最常用的是parallel指令: 这个指令告诉运行时系统并行执行下面的结构化块,即派生( fork)或者启动多个线程来执行该结构化块。 结构化代码块是只有一个入口和一个出口的代码块,尽管结构化代码块允许调用C库函数exit。 被启动的线程的数目依赖于系统,但是大多数系统会为每一个内核开启一个线程。 执行block of code的线程的集合叫做线程组。组中有一个线程在parallel指令之前执行,这个线程叫主线程,其余被parallel指令开启的线程叫做从线程。当所有的线程都结束后,从线程被终止或者合并(join),而主线程继续执行结构化代码块之后的代码。 许多OpenMP指令可以被子句(clauses)修改。使用最频繁的是num_threads子句,当使用OpenMP指令启动线程组时,可以通过修改num_threads子句来启动需要数目的线程。 当OpenMP启动了一组线程后,给每一个线程分配一个线程编号(rank),编号的范围是0,1,…,thread_count – 1。调用OpenMP库函数omp_get_thread_num返回调用该函数的线程编号。函数omp_get_th reads返回当前线程组中线程的数目。 开发共享内存程序时的一个主要问题是可能存在竞争条件。竞争条件发生在多个线程都试图访问一个共享资源,且至少有一个访问是更新的情况下。这些访问可能会产生错误。 每次只能被一个线程更新的共享变量的代码叫做临界区。因此,如果多个线程试图更新一个共享变量,程序就
文档评论(0)