我有一个关于多线程(Openmp 和 C 代码)的问题。
我要在给定文本文件中搜索 16 个不同的词。实现它的方法是创建一个 for 循环,遍历包含要搜索的每个单词的数组。 16 个不同的字意味着可以同时运行 16 个不同的线程。另一种使用多线程的方法是将文本文件分成 x 个大小相似的 block 并同时搜索每个 block 。 我的问题是:我可以使用多线程为每个单词创建一个线程,然后将该特定的子线程拆分为新的子线程来扫描一个大小的数据 block 吗?
如果这不可能/不可行,我想唯一的解决方案是手动将文本文件拆分为不同的字符数组,然后对我要搜索的每个单词使用#pragma。
只会对文本文件执行读取操作,而写入操作仅限于分配给每个单词的变量以用于计数目的。 IE。不会有竞争条件,除非我错过了什么。
最佳答案
首先,16 个词并不意味着 16 个不同的线程。每个线程本身都会带来同步开销、不平等的工作分配、spawn-relax 时间等因素,如果不仔细考虑,将导致完全损害并行性的好处。
在工作数据之间不存在依赖性的情况下,可以极大地利用并行性。您的工作独立于您所表达的任一可能解决方案中的工作数据。要在大量字符中查找某些字符,与字符排列无关(例如,在每个“C”之后查找“++”与查找“++”)。
现在的问题是如何利用内存带宽以及如何通过“分支预测”来解决丢失的问题。
Common Data Different threads 在内存受限的情况下非常好。第一个读取数据的线程会将其加载到缓存中,而其他线程将最终使用这 block 数据。所以数据只会从内存中加载一次。拆分数据也将导致只从内存中加载一次数据,因为每个线程都会加载它的部分,然后刷新出来。因此,两种情况下的内存负载非常相似。
您的代码称为“逻辑绑定(bind)”。分支预测是需要处理的非常重要的方面,但非常棘手。公共(public)数据模块很可能会失败。假设您必须在一百万个球中找到一个红色球。预测将倾向于做出“不存在”的自然选择。但是如果说它在前 100 个球内失败了,那么在这次失败之后所有处理过的球将最终重做并且你回到原点。相反,在拆分的情况下,“重做”的最坏情况不会像普通数据那样糟糕。但我们不能保证这一点。
然后,选择上述任何模块完全取决于您可以使用的架构。
SMT/逻辑核心与物理核心。将上述任何一种方法与 SMT 一起使用都会导致性能降低 w.r.t 相同。物理核心。 您将一个线程拆分为多个子线程的想法 是 SMT 的基础。每个新线程都会增加追逐资源,带来同步开销以及分支预测错误的可能性。在增加物理线程的情况下,分支预测会限制性能。
Splitting or Common data,你的代码是不可扩展的。最好的办法是使用最小号。可用的物理内核。通用数据带来的复杂性较低,并且应该很容易处理。最小号的线程可以通过实验找到。在此值之后,性能将保持不变。
关于c - 将子线程拆分为新的子线程 (Openmp),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16265751/