MPI

2014-06-18 18 views
6

ile türetilmiş veri türleri Fortran'daki BCASTing veri tiplerini öğreniyorum ve terminalden iki değer alan ve her işlemde bunları görüntüleyen bir kod var. Tamsayı/tamsayı/tamsayı/tamsayı/tamsayı/değer2 kombinasyonları için bu çalışır, ancak tamsayı/gerçek * 8 kombinasyonu için başarısız olur.MPI

kodudur:

use mpi 
implicit none 

integer :: ierror, pid, ncpu, root = 0 

integer :: counts, newtype, extent 
integer, dimension(2) :: oldtypes, blockcounts, offsets 

type value 
    integer :: value1 = 0 
    real*8 :: value2 
end type 

type (value) input 

call MPI_INIT(ierror) 
call MPI_COMM_RANK(MPI_COMM_WORLD, pid, ierror) 
call MPI_COMM_SIZE(MPI_COMM_WORLD, ncpu, ierror) 

! setup of 1 MPI_INTEGER field: value1 
offsets(1) = 0 
oldtypes(1) = MPI_INTEGER 
blockcounts(1) = 1 

! setup of 1 MPI_REAL8 field: value2 
call MPI_TYPE_EXTENT(MPI_INTEGER, extent, ierror) !determine offset of MPI_INTEGER 
offsets(2) = blockcounts(1)*extent     !offset is 1 MPI_INTEGER extents 
oldtypes(2) = MPI_REAL8 
blockcounts(2) = 1 

! define struct type and commit 
counts = 2 !for MPI_INTEGER + MPI_REAL8 
call MPI_TYPE_STRUCT(counts, blockcounts, offsets, & 
        oldtypes, newtype, ierror) 
call MPI_TYPE_COMMIT(newtype, ierror) 

do while (input%value1 >= 0) 
    if (pid == root) then 
     read(*,*) input 
     write(*,*) 'input was: ', input 
    end if 
    call MPI_BCAST(input, 1, newtype, & 
        root, MPI_COMM_WORLD, ierror) 
    write(*,*), 'process ', pid, 'received: ', input 
end do 

call MPI_TYPE_FREE(newtype, ierror) 
call MPI_FINALIZE(ierror) 

O gelen deklarasyon değişen ve eskitür tarafından bu tamsayı/tamsayı ve tamsayı/gerçek çalışma cezası kontrol edilebilir. Tamsayı/gerçek * 8 kombinasyonu, örn. girişleri -1 2.0 üreten: benzer bir konu ile

input was:   -1 2.0000000000000000  
process   0 received:   -1 2.0000000000000000  
process   1 received:   -1 0.0000000000000000  
process   2 received:   -1 0.0000000000000000  
process   3 received:   -1 0.0000000000000000 

This iplik dikkate alınmaz ek dolgu olabilir olarak MPI_TYPE_EXTENT kullanarak doğru olmadığını göstermektedir. Maalesef, sorunu çözebiliyor ve burada birisinin beni aydınlatmasına yardımcı olabiliyordum. peşin

thx

cevap

7

Sen Temel fikir hakkına sahip - Yapıyı oluşturduk, ancak tamsayı değeri aşağıdaki çift duyarlıklı değeri hemen saklanır olduğunu varsayıyoruz ve bu genelde doğru değildir . Hristo'nun cevabını vermek için bağlantı kurarsanız, bu soruya iyi bir cevap verir.

Sorun, derleyicinin sizin için veri yapı alanlarınızı normalde align yapacağıdır. Çoğu sistem belleğe hizalı olan değerleri, düzgün olmayan erişimleri gerçekleştirebileceklerinden çok daha hızlı okuyabilir/yazabilirler; Tipik olarak, gereksinim, hizalamanın eleman boyutlarında olmasıdır; 8 baytlık bir çift duyarlık sayısının 8 baytlık sınırlarla hizalanması gerekir (yani, ilk baytın adresi sıfır modulo 8'dir), tamsayı ise yalnızca 4 bayt hizalanmış olmalıdır. Bu neredeyse tam olarak, tamsayı ile çift arasında 4 baytlık dolgu olduğu anlamına gelir.

Çoğu durumda, derleyiciyi bu davranışı gevşetmek için kullanabilirsiniz - Fortran'da, verilerin sürekli olarak depolanmasını gerektirmek için sequence anahtar sözcüğünü de kullanabilirsiniz. Her iki durumda da performans açısından (Fortran ve MPI kullanıyor olmanızın nedeni budur) bu neredeyse hiçbir zaman doğru bir şey değildir, ancak dışarıdan verilen diğer bir bayt-byte-byte uyumluluk için yararlı olabilir. veri türleri veya biçimleri.

Muhtemelen performans nedenleriyle doldurulmuş dolgu malzemesi verildiğinde, programınızdaki hizalama ve kodun üstesinden gelebilirsiniz; ama bu muhtemelen yapılması gereken doğru şey değil; Diğer alanları eklerseniz veya gerçek sayıyı 4 baytlık tek bir hassas sayı vb. olarak değiştirirseniz, kodunuz tekrar yanlış olur. Eğer böyle türetilmiş türleri dizisi olsaydı, sonuncusu öğenin elemanı ve arasındaki doldurma davayı kapsayacak şekilde bu

integer(kind=MPI_Address_kind) :: startloc, endloc  
integer :: counts, newtype 
integer, dimension(2) :: oldtypes, blockcounts, offsets 

type value 
    integer :: value1 = 0 
    double precision :: value2 
end type 

type (value) :: input 

!...  

! setup of 1 MPI_INTEGER field: value1 
call MPI_Get_address(input, startloc, ierror) 
oldtypes(1) = MPI_INTEGER 
blockcounts(1) = 1 
call MPI_Get_address(input%value1, endloc, ierror) 
offsets(1) = endloc - startloc 

oldtypes(2) = MPI_DOUBLE_PRECISION 
blockcounts(2) = 1 
call MPI_Get_address(input%value2, endloc, ierror) 
offsets(2) = endloc - startloc 

if (pid == 0) then 
    print *,'offsets are: ', offsets 
endif 

Not: En açıkça yerleri bulmak için MPI_Get_address kullanmak ve doğru Ofsetleri kendiniz hesaplamaktır Bir sonraki başlangıcında, bunu açıkça ölçmek ve türün genel boyutunu - MPI_Type_create_resized ile - bu türden bir üyenin başlangıcı ve bir sonraki başlangıcının arasındaki uzaklık - ayarlamak isteyebilirsiniz.

+0

+1 harika bir cevap ve örnek. – casey

+0

+1 açıkladığınız için teşekkür ederiz. Zaten MPI_GET_ADDRESS ile uğraşıyordum ama henüz işe yaramadı. örneğiniz güzel çalıştı! – nluigi