2017-03-28 26 views
3

假設AI是整數類型的維數爲N的數組。一般而言,I是整數1:N的置換。我想要做A(1:N) = A(I(1:N))。對於小型N這工作正常,但當N很大時,我得到了Segmentation fault。 這裏是什麼我確實是一個例子:Fortran中使用數組索引的分段錯誤

integer N 
integer,dimension(:),allocatable::A,I 
N = 10000000 
allocate(A(N)) 
allocate(I(N)) 
A = (/ (i,i=1,N) /) 
I = (/ (N-i+1,i=1,N) /) 
A(1:N) = A(I(1:N)) 

有沒有更好的方式來做到這一點?

+3

在你的情況''我'是一個數組,你使用它作爲循環變量?這甚至有可能嗎? – chw21

+1

對於什麼是值得的,在隱含的do循環中使用專用的'ii'變量,即使對於'N' = 100M(gfortran v.5.4),代碼也能正常執行。 – chw21

+1

爲了明確這一點,Fortran不區分大小寫,所以'I'和'i'指向相同的變量。 –

回答

0

看來A(I(1:N))是有效的語法,至少在我的測試中(gfortran 4.8,ifort 16.0,pgfortran 15.10)。一個問題是iI是一樣的東西,並且數組I不能像你一樣在暗示的操作中使用。與j更換它的產量,對我運行一個程序:

program main 
    implicit none 

    integer :: N, j 
    integer, allocatable, dimension(:) :: A, I 

    ! -- Setup 
    N = 10000000 
    allocate(A(N),I(N)) 
    A = (/ (j,j=1,N) /) 
    I = (/ (N-j+1,j=1,N) /) 

    ! -- Main operation 
    A(1:N) = A(I(1:N)) 

    write(*,*) 'A(1): ', A(1) 
    write(*,*) 'A(N): ', A(N) 

end program main 

至於爲什麼你看到分段錯誤,我想你是運行內存時,數組的大小獲得巨大的。如果你仍然有麻煩,但是,我建議如下。

而不是使用A(1:N) = A(I(1:N))的,你真的應該使用一個循環,如

! -- Main operation 
do j=1,N 
    Anew(j) = A(I(j)) 
enddo 
A = Anew 

這是更容易閱讀和調試前進。

+1

你最後一個循環是不正確的,因爲你將在r.h.s.訪問'A'的變化值。我認爲你需要先製作一個副本才能使用這樣的循環。 – agentp

+0

好點@agentp,它現在首先放置在一個虛擬數組中。 – Ross

+0

這樣更好。我猜'A(1:N)= A(I(1:N))'會導致編譯器在後臺創建一個副本.. – agentp