boost graph library:在并行模式下从adjacency_list读取时的访问冲突

时间:2014-04-03 09:34:47

标签: c++ multithreading boost boost-graph adjacency-list

我在并行模式下从boost adjacency_list访问边缘属性时遇到问题。我在C ++代码中使用boost 1.54.0和OpenMP。我的问题归结为以下沙箱示例:

#include <boost/graph/adjacency_list.hpp>

struct Knoten {int Knoten_Property};
struct Pfeil {int Pfeil_Property};
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, Knoten, Pfeil> Graph;
typedef boost::graph_traits<Graph>::edge_descriptor Edge;
typedef boost::graph_traits<Graph>::edge_iterator Edge_iter;

Graph G;

// […] 
// some initializations for the graph. 
// Test graph contains about  20,000 edges

#pragma omp parallel num_threads(4) 
{
    #pragma omp for private(i) 
    for(int i = 0; i < 100; i++) 
    {
        for(pair<Edge_iter, Edge_iter> ei = edges(G); ei.first != ei.second; ++ei.first)
        {
            for (int i = 0; i < 100000; ++i)
            {
                Edge E = *ei.first;
                int my_test = G[E].Pfeil_Property; // (*)
            }
        }
    }
}

运行此代码(并行模式,4个线程)时,我在行(*)读取时获取访问冲突。看起来我不能同时从不同的线程访问边缘的属性,尽管这是一个只读访问。 任何有关此问题的帮助将不胜感激。非常感谢你!

这是整个错误消息(德语);它写道: &#34;例外(第一次机会)...... 在阅读位置时访问违规... 在...&#34;

处未处理的例外情况
Eine Ausnahme (erste Chance) bei 0x000000014042237f in MyApplication.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x000000000257ac58.
Unbehandelte Ausnahme bei 0x000000014042237f in MyApplication.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x000000000257ac58.

1 个答案:

答案 0 :(得分:1)

必须有一些其他东西让你瘫痪,而这些内容在代码片段中是看不到的。我能够使用boost图和openMP

来运行它

更新:我改为使用代码在外循环的每次迭代中显式显示独立工作,并在每个循环中只访问cout一次。

#include <omp.h>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <vector>
#include <string>

using namespace std;

struct Knoten {int Knoten_Property;};
struct Pfeil {int Pfeil_Property;};
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, Knoten, Pfeil> Graph;
typedef boost::graph_traits<Graph>::edge_descriptor Edge;
typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
typedef boost::graph_traits<Graph>::edge_iterator Edge_iter;

string convertInt(int number)
{
   //http://www.cplusplus.com/forum/beginner/7777/
   stringstream ss;//create a stringstream
   ss << number;//add number to the stream
   return ss.str();//return a string with the contents of the stream
}


int main()
{
    Graph G;

    vector<Vertex> verts;

    //add 7 vertices
    for(size_t i = 0; i < 7; ++i){
        Vertex v = add_vertex(G);
        verts.push_back(v);
    }

    add_edge(verts.at(0),verts.at(1),G);
    add_edge(verts.at(0),verts.at(3),G);
    add_edge(verts.at(1),verts.at(2),G);
    add_edge(verts.at(1),verts.at(3),G);
    add_edge(verts.at(1),verts.at(4),G);
    add_edge(verts.at(2),verts.at(4),G);
    add_edge(verts.at(3),verts.at(4),G);
    add_edge(verts.at(3),verts.at(5),G);
    add_edge(verts.at(4),verts.at(5),G);
    add_edge(verts.at(4),verts.at(6),G);
    add_edge(verts.at(5),verts.at(6),G);

    #pragma omp parallel num_threads(4) 
    {
        #pragma omp for private(i) 
        for(int i = 0; i < 10; i++) 
        {
                int threadId = omp_get_thread_num();
        string greeting = "hello from ";
              greeting += convertInt(threadId);
        greeting += " on loop variable ";
        greeting += convertInt(i);
        greeting += " graph edges ";
        greeting += convertInt(num_edges(G));
        greeting += "\n";
        cout << greeting;
        //cout << "edges " << num_edges(G) << endl;
                for(pair<Edge_iter, Edge_iter> ei = edges(G); ei.first != ei.second; ++ei.first)
                {
                    for (int i = 0; i < 10; ++i)
                    {
                     Edge E = *ei.first;
                     int my_test = G[E].Pfeil_Property; // (*)

                  }
              }
          }
    }

    cout << "after join " << num_edges(G) << endl;
    cout << "after join " << num_vertices(G) << endl;

    return 0;
}

编译:BOOST_INC是提升的根,/ usr / lib / gcc ...是omp.h的位置

g++ -O -fopenmp -I $BOOST_INC -I . -I /usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/ -c -g  graphOmp.cpp
g++ -g graphOmp.o -o graphOmp -fopenmp

导出OPM_NUM_THREADS

export OMP_NUM_THREADS=4

输出如下:

hello from 3 on loop variable 9 graph edges 11
hello from 2 on loop variable 6 graph edges 11
hello from 0 on loop variable 0 graph edges 11
hello from 0 on loop variable 1 graph edges 11
hello from 0 on loop variable 2 graph edges 11
hello from 1 on loop variable 3 graph edges 11
hello from 1 on loop variable 4 graph edges 11
hello from 1 on loop variable 5 graph edges 11
hello from 2 on loop variable 7 graph edges 11
hello from 2 on loop variable 8 graph edges 11
after join 11
after join 7

在这里,我们看到每个线程都是for迭代的一部分。连接线程后,只有一个执行线程。您可能需要发布剩余的代码。