【问题标题】:How to add OpenMP for loop by replacing the while loop of a sequential code如何通过替换顺序代码的 while 循环来添加 OpenMP for 循环
【发布时间】:2018-10-25 09:59:36
【问题描述】:

以下代码是按顺序编写的。我想通过将 while 循环替换为 for 循环来实现 OpenMP,但不知道如何执行此操作。我知道 OpenMP 语法但无法实现。

进行并行的原因是为了检查顺序和并行技术之间的性能。有什么帮助吗?

  void block::mine_block(uint32_t difficulty) noexcept
{
    string str(difficulty, '0');

    auto start = system_clock::now();

    while (_hash.substr(0, difficulty) != str)
    {
        ++_nonce;
        _hash = calculate_hash();
    }

    auto end = system_clock::now();
    duration<double> diff = end - start;

    cout << "Block mined: " << _hash << " in " << diff.count() << " seconds" << endl;
}

@Matthieu Brucher - 这会是解决方案吗?

#pragma omp parallel    // start the parallel region
{
    #pragma omp single  // let the while loop execute by one thread and generate tasks
    while (time < TotalTime){

        #pragma omp task
        {
            // this code will be a task that may be executed immediately on a different core or deferred for later execution
        }

    } // end of while loop and single region
    // at this point we also wait until all tasks that were created have finished

} // end of parallel region

通过实现上述代码

#pragma omp parallel                        
    {
        #pragma omp single                      
        while (_hash.substr(0, difficulty) != str) {
            #pragma omp task                    
            {
                ++_nonce;
                _hash = calculate_hash();
            }
        }
    }

【问题讨论】:

  • 可以猜测calculate_hash 的作用以及_nonce 的使用方式,但我宁愿根据事实给出答案。请至少包含一些关于此的信息。避免使用全局变量,而是制定无副作用的函数。使并行化更容易。
  • 我可以提供整个代码吗?
  • 怎么保证block::mine_block不会扔? str 的构造可能会抛出,因为它分配内存(如果存储的字符串不短)。
  • 一般来说,如果每次迭代的效果都依赖于之前的迭代,那么这样的循环是不能并行化的。
  • 整个代码如果很长,并不总是可取的。通常你应该使用minimal reproducible example。我们需要知道的最重要的事情是calculate_hash 是否有任何副作用并使用任何全局数据。同样,假设它确实访问了全局变量_nonce,在尝试并行化之前,您应该首先将其重构为将其作为参数。

标签: c++ multithreading c++11 parallel-processing openmp


【解决方案1】:

问题是您的循环中有依赖项。因此,不可能按原样并行化它。

一个好的第一种方法是使用多个起点并使用多个线程来创建新的哈希值。然后当其中一个线程找到一个很好的匹配时,你会打开一个全局 bool 标志并停止所有线程。

【讨论】:

  • 感谢您的回复。是否有任何文章或教程,以便我可以相应地学习和实施您的评论?
  • 恐怕,为每个线程搜索种子是特定于问题的:/ 然后它只是一个带有原子变量标志的while循环,设置为`_hash.substr(0,难度) == str.
  • 请看上面,我添加了一些东西。谢谢。
  • 如果你有single,那么它不是并行的。不,并行做一个while(not_found),每个线程都有它的本地hash,如果有结果,更新not_found
  • 这就是我所做的。我可以要求你实施你所说的 while(not_found)。谢谢。 #pragma omp parallel { #pragma omp single while (_hash.substr(0,难度) != str) { #pragma omp task { ++_nonce; _hash = 计算_hash(); } } }
最近更新 更多