繁体   English   中英

运行方法并等待完成所有formp循环

[英]Run method and wait to finish all for loops 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";
        }

    }
}

我在gdb中运行了您的代码,对dividors.push_back(...)的调用随机崩溃。 这似乎是一个竞争条件,原因是您要同时更改多个线程的dividors向量,因此在这种意义上, std::vector类不是线程安全的。 参见std :: vector,线程安全,多线程

您要做的是确保没有线程更改矢量,而另一个线程更改或读取矢量。 这用于对每个线程进行排序。 #pragma omp single ,只需对其进行一次排序,尤其是无需一次从多个线程进行排序。

有几种方法可以解决此问题。 最简单的就是使用ordered子句。 请参见下面的代码。 但是,这消除了一些并行性。 更好的方法是在并行块内声明私有的除法向量(我称为dividors_private ),以便每个线程获得其自己的私有版本,然后在关键块中写入dividors向量。 排序是在私有向量上并行进行的。 最后的排序是在单个线程上对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;
}

使用私有除数向量的代码版本

#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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM