OpenMP和智能指针

时间:2016-06-17 19:16:56

标签: c++ pointers openmp shared-ptr smart-pointers

我正在尝试并行化等同于以下代码的内容

#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 << " ";

  }

}

由于我无法控制的原因,以及在示例中无法理解的原因,我需要坚持使用共享指针。这是我目前的尝试:

#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;
  }

}

这会编译并打印0-9系列,但它会给我glibc detected个错误。在过去,我使用相同的策略使用foo=&fooPriv;而不是foo.reset(&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)

1 个答案:

答案 0 :(得分:0)

reset()旨在替换共享对象引用,而不是修改对象本身。内部shared_ptr使用原子进行引用计数,它将在赋值,副本等处递增,并在调用析构函数时减少,并且事物超出范围,直到最终销毁托管对象并释放内存。重置或交换用于替换使用其他实例管理的基础对象。

*foo = obj;应该进行深层复制,前提是赋值运算符被重载,以便对相关的托管对象执行此操作。在您的示例中为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.S。如果您的编译器和工具链也支持它,我们在标准c ++ 11和更新版本中有shared_ptr。它基于boost实现并以相同的方式工作。