2016-06-17 3 views
2

Je suis en train de paralléliser ce qui est équivalent au code suivantOpenMP et pointeurs intelligents

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

    } 

} 

Pour des raisons indépendantes de ma volonté, et qui ne peut être apprécié dans l'exemple, je dois en tenir à la commune aiguille. Ceci est ma tentative actuelle:

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

} 

Cette compile et imprime la série 0-9, mais il me donne glibc detected erreurs. Dans le passé, j'ai travaillé avec des pointeurs nus avec succès en utilisant la même stratégie, avec foo=&fooPriv; au lieu de foo.reset(&fooPriv);, mais il y a quelque chose qui me manque ici. Je soupçonne qu'il a quelque chose à être avec le pointeur supplémentaire à l'intérieur foo qui compte le nombre d'appels, donc je ne fais pas correctement une "copie profonde", comme il est mentionné dans d'autres questions/forums, mais je n'ai pas été capable de le résoudre. Aucune suggestion?

EDIT: La sortie du programme est parfois ceci:

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

Et parfois ceci:

*** 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

Quelle était l'erreur? Cela peut fournir plus de contexte. – AJG85

+0

@ AJG85 Je édite le poste avec la sortie, qui incluent les erreurs. Merci beaucoup! – Israelcma

Répondre

0

reset() est destiné à remplacer la référence d'objet partagé modifie pas l'objet lui-même. Internal_ptr utilise un atomique pour le comptage des références qui incrémentera les affectations, les copies, etc. et les décrémentera au fur et à mesure que les destructeurs sont appelés et que les objets sortent de la portée jusqu'à détruire l'objet géré et libérer la mémoire. Réinitialiser ou échanger est utilisé pour remplacer l'objet sous-jacent géré avec une autre instance.

*foo = obj; doit effectuer une copie complète à condition que l'opérateur d'affectation soit surchargé pour ce faire pour l'objet géré en question. Dans votre exemple, une copie de la valeur int.

foo = maked_shared<int>(fooPriv); peut-être ce que vous voulez pour la copie initiale peut-être? Dans ce cas, vous devez vous assurer que firstOfThread est false après l'initialisation, puis simplement partager la référence entre les autres threads afin qu'ils puissent mettre à jour la valeur. De préférence dans une section critique pour éviter les conditions de déchirement et de course.

Ceci est juste un conseil général car sans savoir quelles erreurs vous avez rencontrées ou ayant une question spécifique, il est difficile de déterminer exactement ce que vous cherchez.

Édition: Mise à jour basée sur le journal des erreurs. On dirait qu'il a essayé de libérer un pointeur invalide. Cela peut être causé par une double suppression ou une référence perdue. Avec un pointeur partagé, vous pouvez l'initialiser avant la section parallèle et compter sur le comptage des références tel qu'il est transmis à chaque pile de threads pour le conserver dans la portée. Protégez ensuite les lectures et les écritures dans la fonction de thread pour éviter les conditions de course.

#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. Nous avons shared_ptr en standard C++ 11 et plus récent si votre compilateur et votre chaîne d'outils le supportent également. Il est basé sur la mise en œuvre de boost et fonctionne de la même manière.

+0

Merci pour votre réponse @ AJG85. Oui, avec la réinitialisation, j'essaie de remplacer uniquement la référence d'objet, de '* foo = -1' à la copie privée op' fooPriv', qui est copiée pour chaque thread car elle se trouve dans 'firstprivate'. Chaque thread a besoin de sa propre copie de '* foo' car il est modifié.Et oui, je mets 'firstOfThread = false' à la fin, puisque chaque thread a besoin d'une copie, pas chaque itération. Si 'foo' était un pointeur nu, cela fonctionne parfaitement en changeant' foo.reset (& fooPriv) 'en' foo = & fooPriv' – Israelcma

+0

La vérification du drapeau et la réinitialisation n'étaient pas protégées, donc il serait possible pour un ou plus de threads à penser qu'ils sont d'abord avant que l'indicateur est défini sur false et le cache est mis à jour pour les autres threads pour voir la nouvelle valeur. Si vous voulez que chacun ait sa propre copie, il n'est peut-être pas nécessaire de partager un pointeur. Je pensais que c'était partagé parce que l'ordre des opérations n'était pas important tant que chacun avait lieu à un moment donné. c'est-à-dire que la valeur de foo serait fixée à l'itération finale du dernier thread à quitter, qui pourrait changer d'un passage à l'autre. – AJG85

+0

J'ai essayé votre code ci-dessus, mais il sort quelque chose comme '0 0 7 1 8 2 9 3 10 4 5'. Cela se produit car un thread peut définir la valeur de 'foo' dans le délai entre l'attribution et l'instruction d'impression de l'autre thread. Cela peut être résolu, dans cet exemple simple, mais en englobant les deux, l'instruction d'attribution et d'impression dans un seul bloc sous critique, mais cela irait à l'encontre de l'objectif de la parallélisation. Et oui, la commande n'a pas d'importance. – Israelcma