2012-07-18 50 views
7

Cấu trúc fortran 2008 do concurrent là một vòng lặp làm cho trình biên dịch không lặp lại ảnh hưởng đến bất kỳ trình duyệt nào khác. Do đó nó có thể được song song một cách an toàn.Song song fortran 2008 `làm đồng thời` một cách có hệ thống, có thể với openmp

Một ví dụ hợp lệ:

program main 
    implicit none 
    integer :: i 
    integer, dimension(10) :: array 
    do concurrent(i= 1: 10) 
    array(i) = i 
    end do 
end program main 

nơi lặp có thể được thực hiện trong bất kỳ thứ tự. Bạn có thể đọc thêm về nó here.

Theo hiểu biết của tôi, gfortran không tự động song song các vòng do concurrent này, trong khi tôi nhớ một thư danh sách phát tán về việc thực hiện nó (here). Nó biến đổi chúng thành các vòng cổ điển do.

Câu hỏi của tôi: Bạn có biết một cách để có hệ thống parallelize do concurrent vòng? Ví dụ: cú pháp mở rộng có hệ thống?

+1

Nếu bạn vẫn còn trên đó - không sử dụng 'FORALL' với' workshare'. Xem có thể cập nhật câu trả lời dưới đây. –

Trả lời

12

Nó không phải là dễ dàng để làm điều đó tự động. Cấu trúc DO CONCURRENTforall-header có nghĩa là nó có thể chấp nhận nhiều vòng, định nghĩa biến chỉ mục và mặt nạ. Về cơ bản, bạn cần phải thay thế:

DO CONCURRENT([<type-spec> :: ]<forall-triplet-spec 1>, <forall-triplet-spec 2>, ...[, <scalar-mask-expression>]) 
    <block> 
END DO 

với:

[BLOCK 
    <type-spec> :: <indexes>] 

!$omp parallel do 
DO <forall-triplet-spec 1> 
    DO <forall-triplet-spec 2> 
    ... 
    [IF (<scalar-mask-expression>) THEN] 
     <block> 
    [END IF] 
    ... 
    END DO 
END DO 
!$omp end parallel do 

[END BLOCK] 

(điều trong dấu ngoặc vuông là không bắt buộc, dựa trên sự hiện diện của các phần tương ứng trong forall-header)

Lưu ý rằng điều này sẽ không hiệu quả như song song một vòng lặp lớn với <iters 1>*<iters 2>*... các lần lặp độc lập, đó là những gì mà DO CONCURRENT được mong đợi thực hiện. Lưu ý rằng forall-header cho phép loại-spec cho phép người dùng xác định chỉ mục vòng lặp bên trong tiêu đề và bạn sẽ cần bao quanh toàn bộ nội dung trong cấu trúc BLOCK ... END BLOCK để bảo toàn ngữ nghĩa. Bạn cũng cần kiểm tra xem vô hướng-mặt nạ-expr có tồn tại ở cuối số forall-header và nếu bạn cũng nên đặt IF ... END IF bên trong vòng lặp trong cùng.

Nếu bạn chỉ có các bài tập mảng bên trong nội dung của DO CONCURRENT, bạn cũng có thể chuyển đổi nó thành FORALL và sử dụng chỉ thị workshare OpenMP. Nó sẽ dễ dàng hơn nhiều so với ở trên.

DO CONCURRENT <forall-header> 
    <block> 
END DO 

sẽ trở thành:

!$omp parallel workshare 
FORALL <forall-header> 
    <block> 
END FORALL 
!$omp end parallel workshare 

Với tất cả ở trên, chỉ hệ thống cách mà tôi có thể nghĩ đến là để có hệ thống đi qua mã nguồn của bạn, tìm kiếm DO CONCURRENTcách có hệ thống thay thế bằng một trong các cấu trúc được chuyển đổi ở trên dựa trên nội dung của forall-header và thân vòng lặp.

Chỉnh sửa: Sử dụng chỉ thị OpenMP workshare hiện không được khuyến khích. Nó chỉ ra rằng ít nhất Intel Fortran Compiler và GCC serialise FORALL báo cáo và xây dựng bên trong OpenMP workshare chỉ thị bằng cách xung quanh chúng với chỉ thị OpenMP single trong quá trình biên dịch mà không mang lại tốc độ nào. Các trình biên dịch khác có thể thực hiện nó một cách khác nhau nhưng tốt hơn là tránh sử dụng nó nếu đạt được hiệu suất di động.

+0

Cảm ơn bạn đã cập nhật. Bạn có một nguồn để đọc về hành vi nản lòng này không? – max

+0

Với GCC, bạn có thể xem [mã nguồn] (http://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch/gcc/fortran/). Một số cấu trúc được song song, ví dụ: gán mảng, nhưng 'FORALL' không nằm trong số đó. Với các trình biên dịch khác, bạn có thể xem kết quả lắp ráp. –

+0

Tôi cũng nên thêm rằng các nhà cung cấp trình biên dịch đang thực sự giải quyết chính xác cùng một vấn đề mà bạn đang cố gắng giải quyết :) –

1

Tôi không chắc chắn ý của bạn là "một cách để song song có hệ thống làm các vòng lặp đồng thời". Tuy nhiên, để đơn giản parallelise một do vòng lặp thông thường với OpenMP bạn chỉ có thể sử dụng một cái gì đó như:

!$omp parallel private (i) 
!$omp do 
do i = 1,10 
    array(i) = i 
end do 
!$omp end do 
!$omp end parallel 

Đây có phải là những gì bạn đang sau?

+0

Xin lỗi vì mơ hồ "có hệ thống". Ví dụ, tôi có thể _grep_ hoặc _awk_ the 'do concurrent'; XX; 'end do' ở mọi nơi trong mã, và thay thế nó (_sed_ hoặc _awk_, chẳng hạn) với cú pháp openmp giống nhau. Không nên xảy ra cụ thể (nhưng biến vòng lặp của khóa học). Câu trả lời của bạn có thể giúp đỡ theo cách này, nhưng nó luôn luôn là cú pháp chính xác cho tất cả các loại công cụ ở giữa 'làm đồng thời' và' kết thúc do'? – max

+0

Theo như tôi biết điều này là đủ, với những hạn chế về những gì có thể đi vào một 'làm đồng thời' xây dựng - hy vọng một người nào đó hiểu biết hơn có thể kêu vang ở đây. Một trong những mối quan tâm tôi có về những gì bạn đang cố gắng làm là khi sử dụng một 'do concurrent' xây dựng trình biên dịch sẽ kiểm tra xem bạn đang làm gì trong cấu trúc được cho phép bởi chuẩn Fortran nhưng điều này sẽ không xảy ra nếu bạn sed/awk vv Vì vậy, nếu bạn mắc lỗi, bản dịch đơn giản này có thể không phù hợp và có thể dẫn đến kết quả không mong muốn có thể khó theo dõi. – Chris

Các vấn đề liên quan