2011-04-24 54 views
1

這真是令我困惑,我會很感激,如果有人能幫助我。意外的段錯誤與__gnu_parallel :: accumulate

(編輯:以爲是一個模板化的問題,我是這個錯誤的)

我要添加下面的類的多個副本與GNU的並行化累積算法(存儲在#include <parallel/numeric>

類故意不做太多,我不認爲這是一個線程碰撞問題?

template<class T> 
class NaturalParameters 
{ 
public: 
    typedef typename std::vector<T>::iterator iterator; 

    NaturalParameters() 
    : m_data(2) //vector with two zeros 
    { } 

    typename std::vector<T>::const_iterator 
    begin() const 
    { 
    return m_data.begin(); 
    } 

    typename std::vector<T>::const_iterator 
    end() const 
    { 
    return m_data.end(); 
    } 

    NaturalParameters<T>& 
    operator+=(const NaturalParameters<T>& other) 
    { 
    //do something 
    return *this; 
    } 

private: 
    std::vector<T> m_data; 
}; 

template<class T> 
inline 
NaturalParameters<T> 
operator+(const NaturalParameters<T>& a, const NaturalParameters<T>& b) 
{ 
    NaturalParameters<T> tmp = a; 
    return tmp+=b; 
} 

我然後運行它

int 
main (int ac, char **av) 
{ 
    std::vector<NaturalParameters<double> > NP(1000); 
    NaturalParameters<double> init; 
    //the following segfaults 
    NaturalParameters<double> NP2 = __gnu_parallel::accumulate(NP.begin(), NP.end(), init); 
    //The following runs fine 
    //NaturalParameters<double> NP2 = std::accumulate(NP.begin(), NP.end(), init); 
} 

這確實讓我困惑 - 我不知道是什麼問題。 我用G ++ 4.4.5,並與編制g++ gnu_parallel.cpp -g -fopenmp

編輯:

需要注意的是這個工程:(999元,而不是1000)

for(size_t i=0;i<1000;++i){ 

    std::vector<NaturalParameters> ChildrenNP(999); 
    NaturalParameters<double> init; 
    NaturalParameters<double> NP = __gnu_parallel::accumulate(ChildrenNP.begin(), ChildrenNP.end(), init); 
    //NaturalParameters<double> NP = std::accumulate(ChildrenNP.begin(), ChildrenNP.end(), init); 
    } 

回溯是:

Program received signal SIGSEGV, Segmentation fault. 
__libc_free (mem=0x12af1) at malloc.c:3709 
3709 malloc.c: No such file or directory. 
    in malloc.c 
(gdb) backtrace 
#0 __libc_free (mem=0x12af1) at malloc.c:3709 
#1 0x00000000004024f8 in __gnu_cxx::new_allocator<double>::deallocate (this=0x614518, __p=0x12af1) at /usr/include/c++/4.4/ext/new_allocator.h:95 
#2 0x0000000000401f0a in std::_Vector_base<double, std::allocator<double> >::_M_deallocate (this=0x614518, __p=0x12af1, __n=18446744073709542049) at /usr/include/c++/4.4/bits/stl_vector.h:146 
#3 0x00000000004017b9 in std::_Vector_base<double, std::allocator<double> >::~_Vector_base (this=0x614518, __in_chrg=<value optimized out>) at /usr/include/c++/4.4/bits/stl_vector.h:132 
#4 0x00000000004013b9 in std::vector<double, std::allocator<double> >::~vector (this=0x614518, __in_chrg=<value optimized out>) at /usr/include/c++/4.4/bits/stl_vector.h:313 
#5 0x00000000004012b8 in NaturalParameters<double>::~NaturalParameters (this=0x614518, __in_chrg=<value optimized out>) at gnu_parallel.cpp:10 
#6 0x00000000004023e7 in __gnu_parallel::for_each_template_random_access_ed<__gnu_cxx::__normal_iterator<NaturalParameters<double>*, std::vector<NaturalParameters<double>, std::allocator<NaturalParameters<double> > > >, __gnu_parallel::nothing, __gnu_parallel::accumulate_selector<__gnu_cxx::__normal_iterator<NaturalParameters<double>*, std::vector<NaturalParameters<double>, std::allocator<NaturalParameters<double> > > > >, __gnu_parallel::accumulate_binop_reduct<__gnu_parallel::plus<NaturalParameters<double>, NaturalParameters<double> > >, NaturalParameters<double> > (begin=..., end=..., o=..., f=..., r=..., 
    base=..., output=..., bound=-1) at /usr/include/c++/4.4/parallel/par_loop.h:127 
#7 0x0000000000401d70 in std::__parallel::accumulate_switch<__gnu_cxx::__normal_iterator<NaturalParameters<double>*, std::vector<NaturalParameters<double>, std::allocator<NaturalParameters<double> > > >, NaturalParameters<double>, __gnu_parallel::plus<NaturalParameters<double>, NaturalParameters<double> > > (begin=..., end=..., init=..., binary_op=..., parallelism_tag=__gnu_parallel::parallel_unbalanced) 
    at /usr/include/c++/4.4/parallel/numeric:99 
#8 0x0000000000401655 in std::__parallel::accumulate<__gnu_cxx::__normal_iterator<NaturalParameters<double>*, std::vector<NaturalParameters<double>, std::allocator<NaturalParameters<double> > > >, NaturalParameters<double> > (begin=..., end=..., init=...) at /usr/include/c++/4.4/parallel/numeric:139 
#9 0x0000000000400e2c in main (ac=1, av=0x7fffffffe188) at gnu_parallel.cpp:59 
+0

我可以重複地創建與GNU平行延伸的一些部分的段錯誤,以及。我懷疑實際上存在一個錯誤。 – 2011-04-24 10:10:14

+0

@sehe,它不是一個參考?它的副本,不是? – Tom 2011-04-24 10:31:03

+0

您需要在'operator + ='中發佈DoSomething。 – Puppy 2011-04-24 10:34:38

回答

3

這肯定看起來像的libstdC++中的錯誤:

/usr/include/c++/4.4/parallel/par_loop。 H:87

# pragma omp single 
     { 
     num_threads = omp_get_num_threads(); 
     thread_results = static_cast<Result*>(
          ::operator new(num_threads * sizeof(Result))); 
     constructed = new bool[num_threads]; 
     } 

但線127將其刪除

delete[] thread_results; 

_ 顯然,thread_results的建設是在一個逐步優化,但刪除聲明WA s從未更新以反映此。優化有道理經過短短newing了陣列(新的結果[NUM_THREADS]),因爲它避免了構建elements._

固定,要

delete thread_results; 

刪除錯誤。你會想把這個報告給gnu開發者。


你可能仍然有性病:: __ cxx1998 ::矢量::運算符=的threadsafety一些residu問題。你可以看看我的意思是使用valgrind。然而,valgrind在那裏報道一個積極的消息是完全可能的。

我只是測試周圍的其他方法:使用時new Result[num_threads]delete[](而不是在GNU源的優化版本),你會得到一個乾淨的valgrind運行的所有道路。我敢肯定,這將是一個誤報,不過我確實提到它的開發者GNU當你報告錯誤

+0

縮小了剩餘的valgrind問題 – sehe 2011-04-24 11:27:41

+0

+1您究竟發現了什麼?我非常感動 - 現在填寫錯誤報告。 – Tom 2011-04-24 11:28:34

+0

噢,我的在這裏http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48750 – sehe 2011-04-24 11:52:21

1

嗯,這是線程。線程很難。即使使用gomp /並行擴展。嘗試helgrind(valgrind --tool=helgrind ./t)。輸出是如此之大...所以不會讓我貼在這裏:)

+0

這是一個整潔的工具,我沒有看到helgrind選項之前。謝謝! – Tom 2011-04-24 10:27:58