c++ - 运行方法并等待完成所有 for 循环 openmp

标签 c++ openmp

我创建了 C++ 方法来查找数字的除数。第二步是在 C++ 中使用 openmp。 不幸的是,我无法管理为什么我的函数 doStuff 会抛出 memory error。可能问题出在线程上,我在所有线程停止之前检查数组。有人可以帮助我吗?

没有必要把我的程序全部看完,问题出在doStuff()

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include "omp.h"

using namespace std;

vector<int> dividors;
int NUMBER = 1000;

bool ifContains(vector<int> element, int dividedNumber)
{
    for(int i=0; i<dividors.size(); i++)
    {
        if(dividors[i] == dividedNumber)
            return true;
    }

    return false;
}

void doStuff()
{
    int sqr = (int) sqrt(NUMBER);
    int sqrp1 = sqr + 1;

    #pragma omp parallel
    {
    #pragma omp for nowait
        for (int i = 1; i < sqrp1; i++)
        {
            if (NUMBER % i == 0)
            {
                if (!ifContains(dividors, i))
                    dividors.push_back(i);

                int dividednumber = NUMBER / i;

                if (!ifContains(dividors,dividednumber))
                    dividors.push_back(dividednumber);
            }
        }


        sort(dividors.begin(), dividors.end());

        #pragma omp for nowait
        for (int i = 0; i < dividors.size(); i++)
        {
            cout << dividors[i] << "\r\n";
        }

    }
}

int main()
{
    doStuff();
    return 0;
}

这个我也试过了,但是不行

void doStuff()
{
    int sqr = (int) sqrt(NUMBER);
    int sqrp1 = sqr + 1;

    #pragma omp parallel
    {
        #pragma omp for
        for (int i = 1; i < sqrp1; i++)
        {

            if (NUMBER % i == 0)
            {
                if (!ifContains(dividors, i))
                    dividors.push_back(i);

                int dividednumber = NUMBER / i;

                if (!ifContains(dividors,dividednumber))
                    dividors.push_back(dividednumber);
            }
        }



        #pragma omp single
        sort(dividors.begin(), dividors.end());

        #pragma omp single
        for (int i = 0; i < dividors.size(); i++)
        {
            cout << dividors[i] << "\r\n";
        }

    }
}

最佳答案

有几种方法可以解决这个问题。最简单的就是使用 ordered 子句。请参阅下面的代码。但是,这消除了一些并行性。更好的方法是在并行 block 中声明 prviate dividors vector (我称之为 dividors_private),这样每个线程都有自己的私有(private)版本,然后写入 dividors vector 关键 block 。排序是在私有(private) vector 上并行完成的。最后的排序是在单个线程中对 dividors 完成的,但由于其中大部分已经排序,所以速度很快。请参见下面的第二个代码:

带顺序的代码版本:

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include "omp.h"

using namespace std;

vector<int> dividors;
int NUMBER = 1000;

bool ifContains(vector<int> dividors, int dividedNumber)
{
    for(int i=0; i<dividors.size(); i++)
    {
        if(dividors[i] == dividedNumber)
            return true;
    }

    return false;
}

void doStuff()
{
    int sqr = (int) sqrt(NUMBER);
    int sqrp1 = sqr + 1;

    #pragma omp parallel
    {
        #pragma omp for ordered
        for (int i = 1; i < sqrp1; i++)
        {

            if (NUMBER % i == 0)
            {
                #pragma omp ordered 
                {
                    dividors.push_back(i);
                    if (!ifContains(dividors, i))
                        dividors.push_back(i);

                    int dividednumber = NUMBER / i;

                    if (!ifContains(dividors, dividednumber))
                        dividors.push_back(dividednumber);
                }
            }
        }

    }
    sort(dividors.begin(), dividors.end());  
    for (int i = 0; i < dividors.size(); i++)
    {
        cout << dividors[i] << "\r\n";
    }
}

int main()
{
    doStuff();
    return 0;
}

使用私有(private)除数 vector 的代码版本

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include "omp.h"

using namespace std;

vector<int> dividors;
int NUMBER = 1000;

bool ifContains(vector<int> dividors, int dividedNumber)
{
    for(int i=0; i<dividors.size(); i++)
    {
        if(dividors[i] == dividedNumber)
            return true;
    }

    return false;
}

void doStuff()
{
    int sqr = (int) sqrt(NUMBER);
    int sqrp1 = sqr + 1;

    #pragma omp parallel
    {
        vector<int> dividors_private;
        #pragma omp for nowait
        for (int i = 1; i < sqrp1; i++)
        {

            if (NUMBER % i == 0)
            {

                dividors_private.push_back(i);
                //printf("i %d\n", i);
                if (!ifContains(dividors_private, i))
                    dividors_private.push_back(i);

                int dividednumber = NUMBER / i;

                if (!ifContains(dividors_private, dividednumber))
                    dividors_private.push_back(dividednumber);
            }
        }
        sort(dividors_private.begin(), dividors_private.end());
        #pragma omp critical
        {
            dividors.insert(dividors.end(), dividors_private.begin(), dividors_private.end());
        }
    }
    sort(dividors.begin(), dividors.end()); 
    for (int i = 0; i < dividors.size(); i++) 
    {
        cout << dividors[i] << "\r\n";
    }
}

int main()
{
    doStuff();
    return 0;
}

关于c++ - 运行方法并等待完成所有 for 循环 openmp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16722990/

相关文章:

c++ - 在我的类头文件中的预编译头文件中包含头文件并在其外部包含头文件

c++ - 结构成员变量不变

r - OpenMP、R 和 MacOS

multithreading - OpenMP:基于 NUMA 的拆分循环

c++ - GCC 编译器警告 : extended initializer lists only available with c++0x

c++ - 析构函数上的 "Assertion Failed"

Python 扩展在处理大型列表时创建无效指针

c - openmp中的rsa算法

macos - 在 gfortran mac 中运行 openMP 时出现非法指令错误

c++ - 如何从不同的线程、OpenMP、C++ 写入文件