2016-06-17 3 views
2

내가 통제 할 수없는 이유 코드OpenMP를 스마트 포인터

#include <iostream> 
#include <boost/shared_ptr.hpp> 
using namespace std; 

typedef boost::shared_ptr<int> intPtr; 

int main(int argc, char **argv) { 

    intPtr foo = intPtr(new int(-1)); 

    for(int i = 0; i<10; i++){ 

    *foo = i; 

    cout << *foo << " "; 

    } 

} 

에게 다음에 해당 무엇을 병렬화하기 위해 노력하고있어, 그이 예에서 알 수없는, 내가 공유에 충실 할 필요가 바늘. 이것은 나의 현재의 시도 : 이것은 컴파일하고 0-9 시리즈를 인쇄

#include <iostream> 
#include <boost/shared_ptr.hpp> 
using namespace std; 

typedef boost::shared_ptr<int> intPtr; 

int main(int argc, char **argv) { 

    intPtr foo = intPtr(new int(-1)); 

    bool firstOfThread = true; 
    int fooPriv = *foo; 

#pragma omp parallel for num_threads(2) firstprivate(firstOfThread,fooPriv,foo) 
    for(int i = 0; i<10; i++){ 

    if(firstOfThread){ 
     foo.reset(&fooPriv); 
    } 

    *foo = i; 

#pragma omp critical 
    cout << *foo << " "; 


    firstOfThread=false; 
    } 

} 

, 그러나 그것은 나에게 glibc detected 오류를주고있다. 과거에는 대신 foo=&fooPriv;과 동일한 전략을 사용하여 맨손으로 작업 했었지만 여기에 누락 된 것이 있습니다. 나는 그것이 여분의 포인터와 함께 뭔가를 가지고 있다고 의심합니다. foo은 전화 번호를 세지 만, 다른 질문/포럼에서 언급했듯이 "딥 - 카피"를 제대로하지는 못합니다. 그것을 해결할 수 있습니다. 어떤 제안?

편집 :이 프로그램의 출력은 때로는 이것이다 :

*** glibc detected *** omp-test: free(): invalid pointer: 0x00007fff5da6a7bc *** 
0 6 1 7 2 8 3 9 4 10 5 Aborted (core dumped) 

그리고 때로는이 :

*** glibc detected *** omp-test: free(): invalid pointer: 0x00007fffc210277c *** 
======= Backtrace: ========= 
/lib64/libc.so.6[0x3853875e66] 
/lib64/libc.so.6[0x385387897a] 
omp-test[0x401bc9] 
omp-test(main+0xab)[0x401ccb] 
/lib64/libc.so.6(__libc_start_main+0xfd)[0x385381ed5d] 
omp-test[0x4018e9] 
======= Memory map: ======== 
00400000-00403000 r-xp 00000000 00:15 9568302       /data/disk01/home/imc/sandbox/scripts/aerie-apps/liff-HealpixSigFluxMapGen/omp-test 
00602000-00603000 rw-p 00002000 00:15 9568302       /data/disk01/home/imc/sandbox/scripts/aerie-apps/liff-HealpixSigFluxMapGen/omp-test 
01339000-017f9000 rw-p 00000000 00:00 0         [heap] 
3853000000-3853020000 r-xp 00000000 fd:00 2359298      /lib64/ld-2.12.so 
385321f000-3853220000 r--p 0001f000 fd:00 2359298      /lib64/ld-2.12.so 
3853220000-3853221000 rw-p 00020000 fd:00 2359298      /lib64/ld-2.12.so 
3853221000-3853222000 rw-p 00000000 00:00 0 
3853400000-3853402000 r-xp 00000000 fd:00 2359303      /lib64/libdl-2.12.so 
3853402000-3853602000 ---p 00002000 fd:00 2359303      /lib64/libdl-2.12.so 
3853602000-3853603000 r--p 00002000 fd:00 2359303      /lib64/libdl-2.12.so 
3853603000-3853604000 rw-p 00003000 fd:00 2359303      /lib64/libdl-2.12.so 
3853800000-385398a000 r-xp 00000000 fd:00 2359302      /lib64/libc-2.12.so 
385398a000-3853b8a000 ---p 0018a000 fd:00 2359302      /lib64/libc-2.12.so 
3853b8a000-3853b8e000 r--p 0018a000 fd:00 2359302      /lib64/libc-2.12.so 
3853b8e000-3853b8f000 rw-p 0018e000 fd:00 2359302      /lib64/libc-2.12.so 
3853b8f000-3853b94000 rw-p 00000000 00:00 0 
3853c00000-3853c17000 r-xp 00000000 fd:00 2359314      /lib64/libpthread-2.12.so 
3853c17000-3853e17000 ---p 00017000 fd:00 2359314      /lib64/libpthread-2.12.so 
3853e17000-3853e18000 r--p 00017000 fd:00 2359314      /lib64/libpthread-2.12.so 
3853e18000-3853e19000 rw-p 00018000 fd:00 2359314      /lib64/libpthread-2.12.so 
3853e19000-3853e1d000 rw-p 00000000 00:00 0 
3854000000-3854083000 r-xp 00000000 fd:00 2359316      /lib64/libm-2.12.so 
3854083000-3854282000 ---p 00083000 fd:00 2359316      /lib64/libm-2.12.so 
3854282000-3854283000 r--p 00082000 fd:00 2359316      /lib64/libm-2.12.so 
3854283000-3854284000 rw-p 00083000 fd:00 2359316      /lib64/libm-2.12.so 
3854400000-3854407000 r-xp 00000000 fd:00 2359320      /lib64/librt-2.12.so 
3854407000-3854606000 ---p 00007000 fd:00 2359320      /lib64/librt-2.12.so 
3854606000-3854607000 r--p 00006000 fd:00 2359320      /lib64/librt-2.12.so 
3854607000-3854608000 rw-p 00007000 fd:00 2359320      /lib64/librt-2.12.so 
3854800000-3854815000 r-xp 00000000 fd:00 2359336      /lib64/libz.so.1.2.3 
3854815000-3854a14000 ---p 00015000 fd:00 2359336      /lib64/libz.so.1.2.3 
3854a14000-3854a15000 r--p 00014000 fd:00 2359336      /lib64/libz.so.1.2.3 
3854a15000-3854a16000 rw-p 00015000 fd:00 2359336      /lib64/libz.so.1.2.3 
3855400000-3855415000 r-xp 00000000 fd:00 1725449      /usr/lib64/libgomp.so.1.0.0 
3855415000-3855614000 ---p 00015000 fd:00 1725449      /usr/lib64/libgomp.so.1.0.0 
3855614000-3855615000 rw-p 00014000 fd:00 1725449      /usr/lib64/libgomp.so.1.0.0 
3855c00000-3855c16000 r-xp 00000000 fd:00 2359508      /lib64/libresolv-2.12.so 
3855c16000-3855e16000 ---p 00016000 fd:00 2359508      /lib64/libresolv-2.12.so 
3855e16000-3855e17000 r--p 00016000 fd:00 2359508      /lib64/libresolv-2.12.so 
3855e17000-3855e18000 rw-p 00017000 fd:00 2359508      /lib64/libresolv-2.12.so 
3855e18000-3855e1a000 rw-p 00000000 00:00 0 
3857800000-3857816000 r-xp 00000000 fd:00 2373979      /lib64/libnsl-2.12.so 
3857816000-3857a15000 ---p 00016000 fd:00 2373979      /lib64/libnsl-2.12.so 
3857a15000-3857a16000 r--p 00015000 fd:00 2373979      /lib64/libnsl-2.12.so 
3857a16000-3857a17000 rw-p 00016000 fd:00 2373979      /lib64/libnsl-2.12.so 
3857a17000-3857a19000 rw-p 00000000 00:00 0 
3857c00000-3857c02000 r-xp 00000000 fd:00 2373980      /lib64/libutil-2.12.so 
3857c02000-3857e01000 ---p 00002000 fd:00 2373980      /lib64/libutil-2.12.so 
3857e01000-3857e02000 r--p 00001000 fd:00 2373980      /lib64/libutil-2.12.so 
3857e02000-3857e03000 rw-p 00002000 fd:00 2373980      /lib64/libutil-2.12.so 
385b800000-385b898000 r-xp 00000000 fd:00 1711172      /usr/lib64/libfreetype.so.6.3.22 
385b898000-385ba97000 ---p 00098000 fd:00 1711172      /usr/lib64/libfreetype.so.6.3.22 
385ba97000-385ba9d000 rw-p 00097000 fd:00 1711172      /usr/lib64/libfreetype.so.6.3.22 
385f400000-385f410000 r-xp 00000000 fd:00 2361304      /lib64/libbz2.so.1.0.4 
385f410000-385f60f000 ---p 00010000 fd:00 2361304      /lib64/libbz2.so.1.0.4 
385f60f000-385f611000 rw-p 0000f000 fd:00 2361304      /lib64/libbz2.so.1.0.4 
38b0800000-38b0816000 r-xp 00000000 fd:00 2366780      /lib64/libgcc_s-4.4.7-20120601.so.1 
38b0816000-38b0a15000 ---p 00016000 fd:00 2366780      /lib64/libgcc_s-4.4.7-20120601.so.1 
38b0a15000-38b0a16000 rw-p 00015000 fd:00 2366780      /lib64/libgcc_s-4.4.7-20120601.so.1 
38b0c00000-38b0ce8000 r-xp 00000000 fd:00 1732781      /usr/lib64/libstdc++.so.6.0.13 
38b0ce8000-38b0ee8000 ---p 000e8000 fd:00 1732781      /usr/lib64/libstdc++.so.6.0.13 
38b0ee8000-38b0eef000 r--p 000e8000 fd:00 1732781      /usr/lib64/libstdc++.so.6.0.13 
38b0eef000-38b0ef1000 rw-p 000ef000 fd:00 1732781      /usr/lib64/libstdc++.so.6.0.13 
38b0ef1000-38b0f06000 rw-p 00000000 00:00 0 
7ffbb8000000-7ffbb8021000 rw-p 00000000 00:00 0 0 6 1 7 2 8 3 9 4 10 5 Aborted (core dumped) 
+0

무엇이 오류입니까? 그것은 더 많은 맥락을 제공 할 수 있습니다. – AJG85

+0

@ AJG85 오류가 포함 된 게시물을 출력으로 편집합니다. 고마워요! – Israelcma

답변

0

reset() 객체 자체를 수정하지 공유 객체 참조를 대체하기위한 것입니다. 내부적으로 shared_ptr은 소멸자가 호출 될 때 할당, 복사 등으로 증가 할 참조 계산을 위해 원자를 사용하며, 결국 관리 대상을 파괴하고 메모리를 해제 할 때까지 범위를 벗어납니다. 리셋 또는 스왑은 다른 인스턴스로 관리되는 기본 객체를 대체하는 데 사용됩니다.

은 문제의 관리 대상에 대해 할당 연산자에 과부하가 걸린 경우 딥 복사해야합니다. 귀하의 예제에서 int 값의 복사본.

foo = maked_shared<int>(fooPriv); 아마도 초기 사본을 원할 수 있습니까? 이 경우 초기화 후에 firstOfThread가 false인지 확인한 다음 다른 스레드에서 참조를 공유하여 값을 업데이트 할 수 있습니다. 바람직하게는 찢어짐과 경쟁 조건을 피하기 위해 중요한 섹션 내에서.

어떤 오류가 발생했는지 또는 구체적인 질문이 없으면 찾고자하는 것을 정확히 찾아 내기가 어렵 기 때문에 이는 일반적인 지침입니다.

편집 : 오류 로그를 기반으로 한 업데이트. 잘못된 포인터를 비우려고 한 것처럼 보입니다. 이중 삭제 또는 참조 손실로 인해 발생할 수 있습니다. 공유 포인터를 사용하면 병렬 섹션보다 먼저 초기화 할 수 있으며 각 스레드 스택에 전달되면 참조 계산에 의존하여 범위를 유지합니다. 그런 다음 스레드 기능 내에서 읽기 및 쓰기를 보호하여 경쟁 조건을 피하십시오.

#include <iostream> 
#include <boost/shared_ptr.hpp> 
using namespace std; 

typedef boost::shared_ptr<int> intPtr; 

int main(int argc, char **argv) { 

    intPtr foo = intPtr(new int(-1)); 

#pragma omp parallel for num_threads(2) firstprivate(foo) 
    for(int i = 0; i<10; i++){ 
#pragma omp critical 
    *foo = i; 
    cout << *foo << " "; 
    } 
    // join or wait for threads to complete here, if needed with OpenMP 
} // foo gets deleted 

P. 컴파일러와 툴 체인이 이것을 지원한다면 표준 C++ 11에서 shared_ptr을 가지고 있습니다. 그것은 부스트 ​​구현을 기반으로하며 동일한 방식으로 작동합니다.

+0

답장을 보내 주신 답장 @ AJG85. 예, 리셋을 사용하면 객체 참조를'* foo = -1'에서 private copy op'fooPriv'로 바꾼다.'fooPriv'는'firstprivate' 안에 있기 때문에 모든 쓰레드에 복사된다. 각 스레드는 수정 된 이후로'* foo'의 복사본을 필요로합니다.그리고 각 스레드는 각각의 반복문이 아닌 복사본이 필요하기 때문에 마지막에는'firstOfThread = false'를 설정합니다. 'foo'가 노출 포인터 인 경우,'foo.reset (& fooPriv)'를'foo = & fooPriv'로 변경하면 완벽하게 작동합니다. – Israelcma

+0

플래그와 리셋의 검사는 보호되지 않았으므로 하나 또는 플래그가 false로 설정되기 전에 더 많은 스레드가 먼저 있다고 생각하고 다른 스레드가 새 값을보기 위해 캐시를 업데이트합니다. 각각의 복사본에 고유 한 복사본이 있으면 포인터를 공유하는 것이 전혀 필요하지 않을 수 있습니다. 나는 그것이 수행되고있는 작업의 순서가 어느 시점에서 각각 일어나는 한 중요하지 않기 때문에 그것이 공유되었다고 생각하고 있었다. 즉 foo의 값은 하나의 실행에서 다음 실행으로 바뀔 수있는 종료 할 마지막 스레드의 최종 반복으로 설정됩니다. – AJG85

+0

위 코드를 시도했지만 '0 0 7 1 8 2 9 3 10 4 5' 같은 것을 출력합니다. 이것은 하나의 스레드가 다른 스레드의 할당 문과 인쇄 문 사이의 시간에'foo'의 값을 설정할 수 있기 때문에 발생합니다. 이 간단한 예제에서는이 문제를 해결할 수 있지만 할당 및 인쇄 문을 모두 하나의 블록에 포함하면 중요하지만 병렬 처리의 목적을 상실 할 수 있습니다. 그리고 예, 순서는 중요하지 않습니다. – Israelcma