【问题标题】:Execution time goes up the more threads I use OpenMP, what's wrong?我使用 OpenMP 的线程越多,执行时间就越长,这是怎么回事?
【发布时间】:2020-02-07 12:38:10
【问题描述】:

我编写了一个程序,它接收字典并查找字典中所有回文单词。我试图并行化这本词典的浏览,以及使用 OpenMP 检查单词是否为回文的逻辑的执行。但是,当我注意到执行时间随着我允许程序使用越来越多的线程而增加时。对此有何解释?我的代码有错误吗?

#pragma omp parallel    //block of code that we want to execute using multiple threads
#pragma omp single  //we only want one thread to iterate through the foor loop and spawn tasks for the other threads
{
    #pragma omp task untied     /* iterating through the for loop is the main task, so 
                     * burden should be shared if execution is suspended
                     */
    {
        for (set<string>::iterator i = wordList.begin(); i != wordList.end(); ++i){
        #pragma omp task    //spawn the tasks of evaluating whether each word should be inserted into palindrome list
            {
                if (isPalindrome(*i)){  //if the word is by itself a palindrome, insert
                    palindromes.insert(*i);
                }
                /* if the reverse of the current word is in the wordlist and it hasn't already been inserted,
                 * insert them both into set of palindromes
                 */ 
                else if (wordList.find(reverseWord(*i)) != wordList.end()){
                    if(palindromes.find(*i) == palindromes.end()){
                        palindromes.insert(*i);
                        palindromes.insert(reverseWord(*i));
                    }
                }
            }
        }
    }
}

我使用对 omp_set_num_threads(Argv[1]) 的调用来更改运行时允许的最大线程数。我在超级计算机上执行这个程序,所以我不认为这是我的计算机“过载”或其他问题的问题。是什么赋予了?我是否误解了如何使用 OpenMP?我在此代码块之前和之后使用了两次对 omp_get_wtime() 的调用来测量执行时间。

编辑:回文和 wordList 都是 std::set,isPalindrome 通过指针操作检查单词是否为回文,reverseWord 针对字符返回单词反转字符(对于此任务,回文也是在单词表,例如,saw - was。

【问题讨论】:

  • palindromes 的并发使用和修改使其非常不可并行化(如果这是一个词)。
  • 怎么样?每个线程都在评估是否将唯一元素插入回文。大多数单词都没有插入,即使是并发插入到集合中也不应该是并行化 imo 的固有问题。
  • 什么是palindromes?如果std::set,那么,你不能在没有同步的情况下并行插入。标准库中的容器不是线程安全的
  • Edit 问题要包括缺少的细节,至少缺少变量声明(palindromeswordlist),isPalindrome 的定义。我们需要minimal reproducible example 才能有机会给出一个好的答案(而不是猜测)。
  • 仍然不是minimal reproducible example。我们需要查看函数定义,而不是描述。如果这些函数进行任何类型的内存分配 - 包括按值传递字符串参数 - 这将对并行化产生非常严重的影响。

标签: c++ concurrency parallel-processing openmp


【解决方案1】:

每个任务执行的计算量(CPU 周期)是否弥补了为生成它们所做的工作?

我可能会建议在此处的任务上使用#pragma omp parallel for,因为您的单词集在整个操作期间具有固定的大小。然而,问题在于将单词插入palindromes 列表时的关键会话。

【讨论】:

  • 我愿意,但我不能为每个循环使用#pragma omp parallel for。我将不得不遍历 wordlist 一次并将迭代器的指针复制到一个数组中,然后遍历该数组。我认为这会更慢,因为在这种情况下我会遍历整个事情。我不认为同时插入回文是一个问题,因为我从来没有插入同一个词,打印出来的答案是好的。
【解决方案2】:

根据(当前)缺失代码的描述,问题在于您反复创建新的string 对象以传递给isPalindrome 和其他地方。每个字符串复制都会导致内存分配(以及随后的空闲),标准内存分配器是不可重入的,如果另一个线程正在分配,则会阻塞一个线程。

一种部分解决方案是将参数作为const std::string &amp; 传递给isPalindrome,这样可以避免复制。 reverseWord 在这方面会有点问题,因为它需要返回一个修改后的字符串,但参数仍然可以通过引用传递。

【讨论】:

    猜你喜欢
    • 2022-11-03
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 2014-11-26
    相关资源
    最近更新 更多