C++ 分配错误在 OpenMPI For 循环中将对象添加到向量(或双端队列或列表)

C++ Alloc Errors Adding Objects to Vector (or Deque or List) in an OpenMPI For Loop

我正在使用为 OpenMPI 编译的 C++(为 Windows 和 Linux 编写)。将 class 对象添加到 OpenMPI for 循环内的向量时,我遇到了一系列奇怪的分配错误。调试显示分配错误的变化模式,所有错误都以我的 "AddEntry()" 方法为中心,但错误永远不会出现在循环中的一致位置或我正在添加的对象中的一致成员上(因此,我相信对象不是问题,这些细节不包含在问题代码中)。我尝试为向量保留 space 并尝试使用双端队列和列表的解决方案。我尝试将对象作为对象、引用和指针(用 'new ()' 实例化)传递给添加成员,这些解决方案的 none 解决了这个问题。这是我的代码:

#include "MyEntryClass.h"
#include "MyVectorClass.h"

#include <omp.h>

CMyVectorClass::CMyVectorClass()
{
    try
    {
        m_vEntries.clear();
        m_vEntries.reserve(750000);
    }
    catch (exception ex)
    {
        cout << "ERROR [CMyVectorClass] Exception Code:  " << ex.what() << "\n";
    }
}

//  Interface (public)

bool CMyVectorClass::AddEntry(CMyVectorClass_Entry& eAdd)
{
    try
    {
        m_vEntries.push_back(eAdd);

        return true;
    }
    catch (exception ex)
    {
        cout << "ERROR [AddEntry] Exception Code:  " << ex.what() << "\n";
    }

    return false;
}

bool CMyVectorClass::DoOMPLoop()
{
    //  Max processors for omp
    int nMaxProcs
    //  Continue, if true
    volatile bool vbContinue = true;
    //  Loop counter
    long lMaxCount = 100000;

    try
    {
        //  Iterate through files
        //  Declare team size
        #pragma omp parallel for shared(vbContinue) num_threads(nMaxProcs)
        for (long lCount = 0; lCount < lMaxCount; lCount++)
        {
            //  The entry object to add
            CMyEntryClass cAdd;

            //  Do some stuff to the entry
            cAdd.SetStuff();

            //  Catalog the data
            vbContinue = AddEntry(cAdd);
        }
    }
    catch (exception ex)
    {
        cout << "ERROR [DoOMPLoop] Exception Code:  " << ex.what() << "\n";
    }

    return false;
}

//  Implementation (private)

这个问题让我花了很长时间试图解决这个问题,none 我在 Whosebug(或整个网络)上找到的帮助使我能够解决这个问题(尽管它帮助我优化了其他代码)。请协助。

经过多次尝试和磨难,我意识到分配错误不是问题的根源(因为我的机器有 beaucoup 内存并且保留限制从未接近超过)。我开始怀疑 OpenMPI for 循环中的 AddEntry() 方法引发了冲突。所以我使用 "resize" 而不是 "reserve" 并且我使用索引 "SetEntryAtIndex()" 函数来简单地在向量中的给定位置重置对象(注意,这种随机访问是不允许的所有类似的容器)。这是我的代码:

#include "MyEntryClass.h"
#include "MyVectorClass.h"

#include <omp.h>

CMyVectorClass::CMyVectorClass()
{
    try
    {
        m_vEntries.clear();
        m_vEntries.resize(750000);
    }
    catch (exception ex)
    {
        cout << "ERROR [CMyVectorClass] Exception Code:  " << ex.what() << "\n";
    }
}

//  Interface (public)

bool CMyVectorClass::SetEntryAtIndex(CMyVectorClass_Entry& eSet, long lIndex)
{
    try
    {
        if ((lIndex >= 0) && (lIndex < m_vEntries.size()))
        {
            m_vEntries[lIndex] = eSet;

            return true;
        }
        else
        {
            ReportTimeStamp("[SetEntryAtIndex]", "ERROR:  Index [" + ConvertLongToString(lIndex) + "] is Out of Range [0:" + ConvertLongToString(m_vEntries.size()) + "]");
        }
    }
    catch (exception ex)
    {
        cout << "ERROR [SetEntryAtIndex] Exception Code:  " << ex.what() << "\n";
    }

    return false;
}

bool CMyVectorClass::DoOMPLoop()
{
    //  Max processors for omp
    int nMaxProcs
    //  Continue, if true
    volatile bool vbContinue = true;
    //  Loop counter
    long lMaxCount = 100000;

    try
    {
        //  Iterate through files
        //  Declare team size
        #pragma omp parallel for shared(vbContinue) num_threads(nMaxProcs)
        for (long lCount = 0; lCount < lMaxCount; lCount++)
        {
            //  The entry object to add
            CMyEntryClass cAdd;

            //  Do some stuff to the entry
            cAdd.SetStuff();

            //  Catalog the data
            vbContinue = SetEntryAtIndex(cAdd, lCount);
        }
    }
    catch (exception ex)
    {
        cout << "ERROR [DoOMPLoop] Exception Code:  " << ex.what() << "\n";
    }

    return false;
}

//  Implementation (private)

诀窍是调整大小以创建一个完全(甚至 OVER)填充的向量,然后使用索引来确保 OpenMPI 循环内没有冲突。

我认为第一个片段肯定还有其他问题。也许您正在破坏未显示的代码中的矢量?下面的小片段或多或少做了同样的事情并且工作正常。请注意,循环会越过结尾,向量会自行调整大小。

#include <vector>

int main(int arg,char*arv[])
{

   std::vector <int> my_vec;

   my_vec.clear();
   my_vec.resize(750000);

   for(int i=0;i<760000;i++)
     my_vec.push_back(i);
   return 0;
}

--马特