OpenMP和智能指针

OpenMP and smart pointers

本文关键字:指针 智能 OpenMP      更新时间:2023-10-16

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

#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)

reset()旨在替换共享对象引用不修改对象本身。内部共享的_ptr使用一个原子来进行参考计数,该参考计数将在调用灾难的分配,副本等上递增,并减少攻击器,并且事物范围不超出范围,直到最终破坏了托管对象并释放内存。重置或交换用于替换用另一个实例管理的基础对象。

*foo = obj;应该进行深层副本,前提是对所讨论的托管对象负载分配运算符为此。在您的示例中,int值的副本

foo = maked_shared<int>(fooPriv);可能是您想要的初始副本吗?在这种情况下,您需要确保初始化后的第一个线程是错误的,然后仅在其他线程上共享参考,以便它们可以更新值。最好在关键部分中避免撕裂和种族条件。

这只是一般指导,因为不知道您遇到的错误或有一个特定的问题,很难确切地指出您要寻找的内容。

编辑:基于错误日志更新。看起来它试图释放无效的指针。这可能是由双重删除或丢失的参考引起的。使用共享指针,您可以在并行部分之前对其进行初始化,并依靠参考计数,因为它传递给每个线程堆栈以保持范围。然后保护线程功能中的任何读取和写入以避免比赛条件。

#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中拥有共享的_ptr,如果您的编译器和工具链也支持它,则我们更新了。它基于增强实施,并以相同的方式工作。