2012-05-24 25 views
5

Tôi có một "mảng mặt nạ" mà tôi muốn thêm vào mảng khác - Nói cách khác, tôi có 3 mảng, A, Bmask. Câu hỏi của tôi là cách hiệu quả nhất (về mặt thời gian thực hiện) là gì để lưu trữ mặt nạ (như một mảng logic, như là một mảng thực của những cái và số không)?Cách hiệu quả nhất để thêm một mảng mặt nạ vào một fortran

EDIT

Dưới đây là một chương trình đồ chơi bạn có thể chơi xung quanh với (nếu bạn có mpif77):

program main 
    implicit None 
    include 'mpif.h' 
    integer, parameter :: ntry=10000 
    integer, parameter :: asize=1000000 
    real,dimension(asize) :: A,B,maskr 
    logical,dimension(asize) :: mask 
    real*8 :: dd,dt,dtave,dtbest 
    integer i 

    do i=1,asize 
    maskr(i)=mod(i,2) 
    mask(i)=.False. 
    if(mod(i,2).eq.0) mask(i)=.True. 
    enddo 

    A=1.0; B=1.0 
    dtbest=1d33 
    dtave=0.0 
    do i=1,ntry 
    dt=mpi_wtime() 
    call add_arrays_logical(asize,A,B,mask) 
    dt=mpi_wtime()-dt 
    dtbest=min(dt,dtbest) 
    dtave=dtave+dt 
    enddo 
    print*,"==== logical ===" 
    print*,"Average",dtave/ntry 
    print*,"Best",dtbest 

    A=1.0; B=1.0 
    dtbest=1d33 
    dtave=0.0 
    do i=1,ntry 
    dt=mpi_wtime() 
    call add_arrays_real(asize,A,B,maskr) 
    dt=mpi_wtime()-dt 
    dtbest=min(dt,dtbest) 
    dtave=dtave+dt 
    enddo 
    print*,"==== Real ===" 
    print*,"Average",dtave/ntry 
    print*,"Best",dtbest 

    A=1.0; B=1.0 
    dtbest=1d33 
    dtave=0.0 
    do i=1,ntry 
    dt=mpi_wtime() 
    where(mask) A=A+B 
    dt=mpi_wtime()-dt 
    dtbest=min(dt,dtbest) 
    dtave=dtave+dt 
    enddo 
    print*,"==== Where ====" 
    print*,"Average",dtave/ntry 
    print*,"Best",dtbest 

    end 

    subroutine add_arrays_logical(n,A,B,mask) 
    integer n 
    real A(n),B(n) 
    logical mask(n) 
    do i=1,n 
    if(mask(i))then 
     A(i)=A(i)+B(i) 
    endif 
    enddo 
    end 

    subroutine add_arrays_real(n,A,B,mask) 
    integer n 
    real A(n),B(n),mask(n) 
    do i=1,n 
    A(i)=A(i)+mask(i)*B(i) 
    enddo 

    end 

kết quả của tôi:

(gfortran -O2)

==== logical === 
Average 1.52590200901031483E-003 
Best 1.48987770080566406E-003 
==== Real === 
Average 1.78022863864898680E-003 
Best 1.74498558044433594E-003 
==== Where ==== 
Average 1.48216445446014400E-003 
Best 1.44505500793457031E-003 

(gfortran O3 -funroll-vòng -ffast-math)

==== logical === 
Average 1.47997992038726811E-003 
Best 1.44982337951660156E-003 
==== Real === 
Average 1.40655457973480223E-003 
Best 1.37186050415039063E-003 
==== Where ==== 
Average 1.48403010368347165E-003 
Best 1.45006179809570313E-003 

(pfg90 -fast) - trên một máy rất cũ

==== logical === 
Average 5.4871437072753909E-003 
Best 5.4519176483154297E-003 
==== Real === 
Average 4.6096980571746831E-003 
Best 4.5847892761230469E-003 
==== Where ==== 
Average 5.3572671413421634E-003 
Best 5.3288936614990234E-003 

(pfg90 -O2) - trên rất cũ máy

==== logical === 
Average 5.4929971456527714E-003 
Best 5.4569244384765625E-003 
==== Real === 
Average 5.5974062204360965E-003 
Best 5.5701732635498047E-003 
==== Where ==== 
Average 5.3811835527420044E-003 
Best 5.3341388702392578E-003 

Tất nhiên, có một vài điều mà có thể ảnh hưởng này - khả năng biên dịch để vectorize các vòng ví dụ - như vậy là có một quy tắc của ngón tay cái về làm thế nào một cái gì đó như thế này cần đạt được?

Trả lời

3

Nếu bằng flops bạn có nghĩa là các hoạt động điểm trôi thì tùy chọn đầu tiên rõ ràng là tốt hơn vì trong trường hợp đó bạn có 1 lần lặp trên mỗi vòng lặp nơi mặt nạ (n) == .true. . Trong khi đó đối với tùy chọn thứ hai, bạn có 2 lần lặp trên mỗi vòng lặp bất kể giá trị của mặt nạ (n).

OTOH, nếu bạn quan tâm đến việc giảm thiểu thời gian thực hiện chức năng này, tại sao bạn không thử cả hai phiên bản trên dữ liệu của mình và kiểm tra nhanh hơn?

Bạn cũng có thể muốn thử nghiệm một phiên bản mà bạn sử dụng Fortran 90 + Ở ĐÂU xây dựng

where(mask) A = A + B 
+0

Mã tôi đang làm việc là f77 (không phải lựa chọn của tôi) - vì vậy tôi tránh 'ở đâu' vì lý do đó. – mgilson

+0

Và có, tôi có nghĩa là về thời gian dành cho chức năng. Tôi sẽ chỉnh sửa. – mgilson

+0

Tôi có thể trả lời nhanh hơn bằng cách sử dụng 'gfortran' vì đó là trình biên dịch duy nhất mà tôi có quyền truy cập dễ dàng - nhưng mã có nghĩa là chạy trên tất cả các loại nền tảng với tất cả các loại trình biên dịch, vì vậy tôi đã tự hỏi có một quy tắc chung cho loại điều này. Nếu không có quy tắc chung, có lẽ không đáng lo ngại về ... – mgilson

5

Tại sao không sử dụng "ở đâu"?

where (mask) A = A + B 

Có thể sử dụng mặt nạ là nhanh nhất nhưng cách duy nhất để biết chắc chắn là đo lường.

+0

Mã tôi đang làm việc là f77 (không phải lựa chọn của tôi) - vì vậy tôi tránh 'ở đâu 'vì lý do đó. – mgilson

+0

Tại sao bạn nghĩ rằng việc sử dụng 'mặt nạ' sẽ nhanh hơn' maskr'? Tôi đã có thể nghĩ rằng 'mặt nạ' sẽ dẫn đến một truy cập bộ nhớ rối loạn hơn so với' maskr' ... – mgilson

+0

@mgilson: Tại sao nó bị "rối loạn"? Bạn vẫn đang lặp tuần tự trên A, B và mặt nạ. Trong trường hợp nắm tay bạn chỉ không chạm vào mọi thành phần của A và B, nhưng vậy thì sao? – janneb

0

Làm thế nào về A = A + maskr*B? Điều đó loại bỏ hoàn toàn bất kỳ hành vi có điều kiện nào, với chi phí quét tất cả ba mảng bất kể sự thưa thớt của mặt nạ của bạn.

1

Không có cách tuyệt đối để xác định điều này trước, vì nó là tất cả các trình biên dịch, nền tảng và vấn đề phụ thuộc. Chỉ là một minh họa, xem các điểm chuẩn thông qua các trình biên dịch Fortran khác nhau trên trang web của Polyhedron.

... mặc dù có một số vấn đề với tiêu chuẩn của Intel, vì đôi khi Intel bị phạt 10 triệu USD bởi Bộ Tư pháp vì cố ý ngăn cản trình biên dịch của họ trên bất kỳ thứ gì khác so với CPU của Intel, v.v.)

Nói xong, một vài suy nghĩ:

1) Một số chiến lược có một "chi phí thiết lập" lớn hơn, trong khi những người khác có "chi phí thực hiện" cao hơn. Đó là, trình biên dịch/mã mất một thời gian để gửi các bit bên phải đến cpu/microinstructions, trong đó có lượng thời gian khác nhau với các chiến lược khác nhau. Như vậy, một chiến lược có thể làm tốt hơn khi thêm các mảng ngắn, trong khi một chiến lược khác có thể làm tốt hơn với các mảng dài.

Có thể có các vấn đề tương tự đối với các trường hợp Mặt nạ của bạn "đậm đặc" so với "thưa thớt" (xem bên dưới).

2) Thông số chuẩn của bạn quá nhỏ. Một nguyên tắc chung cho điểm chuẩn là nó cần ít nhất một vài - mười giây của exe. Với điểm chuẩn của bạn, thời gian thực hiện quá nhỏ đến nỗi bất kỳ sự khác biệt nhỏ nào trong đồng hồ v.v ... đều có thể có hiệu ứng tương đối lớn. Để thấy điều này một cách rõ ràng, hãy chạy tiêu chuẩn Linpack chuẩn cho các trường hợp yêu cầu một phần nhỏ giây, 1-2 giây và 7-10 giây. Nói chung, kết quả dưới 1 giây là vô nghĩa đối với ví dụ đó. Có thể (hoặc ít nhất là, chưa được thử nghiệm gần đây) để F77 chạy nhanh hơn trên một số cấu trúc trong một số điều kiện so với cấu trúc F90/95 (ForAll, Where, v.v.).

Nếu trình biên dịch của bạn cho phép sử dụng phần mảng làm chỉ mục, thì đôi khi (ví dụ: khi Mặt nạ "thưa thớt") tốt hơn trước tiên hãy tạo một mảng nguyên giữ các chỉ mục mảng là True và sau đó chỉ thêm đúng mảng mảng. Ví dụ, nếu Integer iIndex (:) giữ .True. chỉ số giá trị của Mask, sau đó một cái gì đó như A (iIndex ("giới hạn")) + B (iIndex ("giới hạn")) có thể khá hiệu quả, vì chi phí tạo ra một chỉ mục với logic là nhỏ hơn so với các phép toán số học chung. Vì vậy, mặc dù thêm "thiết lập" chi phí, nếu nó là một vấn đề "thưa thớt", sau đó có thể chỉ có một số lượng nhỏ bổ sung vv yêu cầu. Phép nhân và số học cao hơn thậm chí còn đắt hơn, và thậm chí còn rõ rệt hơn với các biến thể thưa thớt. Đây là một loại "nhà làm" ở đâu/ForAll xây dựng.

Ngẫu nhiên, có thể có sự khác biệt về exe ngay cả với (rõ ràng) cùng trình biên dịch. Ví dụ, Simply Fortran thực hiện khá tốt việc tạo mã nhanh, nó sử dụng GCC/gFortran, so với Photran/Eclipse (trên Windows), cũng sử dụng GCC/gFortran (ít nhất là trên một trong các máy của tôi). Điều này có thể là do các cách khác nhau "xen kẽ" MingW hoặc CygWin, v.v. và cũng có thể là do, ví dụ, tối ưu hóa đơn giản của Fortran cho các chip và tập lệnh cụ thể, vv Một số vấn đề không nảy sinh trên Linux vv, và cũng là một ví dụ về các vấn đề "nền tảng".

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