【问题标题】:boost graph library: access violation in reading from adjacency_list in parallel modeboost 图形库:在并行模式下从 adjacency_list 读取访问冲突
【发布时间】:2014-04-03 09:34:46
【问题描述】:

我无法以并行模式从 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 个线程),我在第 (*) 行读取时遇到访问冲突。似乎我无法从不同的线程同时访问边缘的属性,尽管这是只读访问。 对此问题的任何帮助将不胜感激。非常感谢!

这是完整的错误信息(德语);上面写着: “例外(第一次机会)... 在位置读取时访问冲突... 未处理的异常..."

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.

【问题讨论】:

  • 可能很有趣:Parallel Boost Graph Library boost.org/doc/libs/1_55_0/libs/graph_parallel/doc/html/…
  • 请显示完整的错误信息。
  • 感谢您的回答。关于 Parallel Boost Graph Library,据我所知,这是为了在多个处理器上分布图。但是,就我而言,该图没有分布(也不应该分布);我只想从多个线程访问边缘属性。
  • 您对分布式并行 bgl 的权利,在这里无济于事。既然它说的是未处理的异常,你有没有试过在 try catch 中包围它并打印 std::exception.what()?
  • 另一个想法是在内部 for 循环中使用 i。它可能掩盖了 openMP 用于并行化的 i。只是一个想法。没有 openmp 经验。

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


【解决方案1】:

一定有其他东西让你绊倒,而这些东西在 sn-p 中是看不到的。我能够使用 boost graph 和 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是boost的根目录,/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 迭代的一部分。线程加入后,只有一个执行线程。您可能需要发布其余代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    相关资源
    最近更新 更多