2017-02-20 25 views
3

我正在開發具有編譯語言(Fortran 95)的代碼,該編譯語言對大型星系目錄進行了某些計算。每次執行一些更改時,我都會編譯並運行代碼,只需要用磁盤上的星系數據讀取ASCII文件大約需要3分鐘。這是浪費時間。訣竅在成本彙編之間更快地從硬盤中讀取數據

如果我在IDL或Matlab中開始這個項目,那麼它會有所不同,因爲包含數組數據的變量將保存在不同編譯之間的內存中。

但是,我認爲可以做一些事情來加速來自磁盤的令人不安的讀取,例如將文件放在假的RAM分區或其他東西中。

+0

爲了更好地匹配我選擇的答案,我稍微更改了標題。這個答案並不適合我原來的答案100%(沒有關於如何在RAM中做分區的線索),但它不太有用,不會獎勵它的綠色標籤。我將特意發佈有關RAM目錄的另一個問題。 – Mephisto

+1

您是否做了一些實際測量,或者您是否猜測瓶頸是磁盤I/O而不是解析ASCII數據格式?假設你有足夠的RAM用於虛擬硬盤,你可能還有足夠的磁盤緩存可用,所以很可能你已經大部分都是從內存中讀取數據。接受的答案暗示了這一點。 –

+0

@DanMašek我忽略了你提出的具體內容,但是我認爲登錄後第一次執行代碼的時間要比連續讀取的時間長。另外,當文件正在讀取時,TOP命令不會顯示100%的cpu活動,所以可能是硬盤讀取問題。 – Mephisto

回答

6

而不是在RAM磁盤上的細節我建議你從ASCII數據庫切換到二進制。這裏是一個非常簡單的例子...隨機數的數組,存儲爲ASCII(ASCII.txt)和二進制日期(binary.bin):

program writeArr 
    use,intrinsic :: ISO_Fortran_env, only: REAL64 
    implicit none 
    real(REAL64),allocatable :: tmp(:,:) 
    integer :: uFile, i 

    allocate(tmp(10000,10000)) 

    ! Formatted read 
    open(unit=uFile, file='ASCII.txt',form='formatted', & 
     status='replace',action='write') 
    do i=1,size(tmp,1) 
    write(uFile,*) tmp(:,i) 
    enddo !i 
    close(uFile) 

    ! Unformatted read 
    open(unit=uFile, file='binary.bin',form='unformatted', & 
     status='replace',action='write') 
    write(uFile) tmp 
    close(uFile) 

end program 

下面是結果在大小方面:

:> ls -lah ASCII.txt binary.bin 
-rw-rw-r--. 1 elias elias 2.5G Feb 20 20:59 ASCII.txt 
-rw-rw-r--. 1 elias elias 763M Feb 20 20:59 binary.bin 

因此,您在存儲方面節省了約3.35倍。 現在到了有趣的部分:在...

program readArr 
    use,intrinsic :: ISO_Fortran_env, only: REAL64 
    implicit none 
    real(REAL64),allocatable :: tmp(:,:) 
    integer :: uFile, i 
    integer :: count_rate, iTime1, iTime2 

    allocate(tmp(10000,10000)) 

    ! Get the count rate 
    call system_clock(count_rate=count_rate) 

    ! Formatted write 
    open(unit=uFile, file='ASCII.txt',form='formatted', & 
     status='old',action='read') 

    call system_clock(iTime1) 
    do i=1,size(tmp,1) 
    read(uFile,*) tmp(:,i) 
    enddo !i 
    call system_clock(iTime2) 
    close(uFile) 
    print *,'ASCII read ',real(iTime2-iTime1,REAL64)/real(count_rate,REAL64) 

    ! Unformatted write 
    open(unit=uFile, file='binary.bin',form='unformatted', & 
     status='old',action='read') 
    call system_clock(iTime1) 
    read(uFile) tmp 
    call system_clock(iTime2) 
    close(uFile) 
    print *,'Binary read ',real(iTime2-iTime1,REAL64)/real(count_rate,REAL64) 

end program 

回讀的結果是

ASCII read 37.250999999999998  
Binary read 1.5460000000000000 

所以,> 24的一個因素!

因此,不要考慮其他任何事情,請先切換到二進制文件格式。

+0

當然,還有很多二進制格式更適合複雜的數據,並且比簡單的Fortran二進制文件更具可移植性。其中我建議你考慮HDF5。 –

+0

這是一個非常棒的答案,對很多人來說都很有用(+1),但是原始文件有多種類型(第1列是字符,第2列是整數,其他列是浮點...),我定義了派生類型。編寫二進制文件時,我不確定如何處理這個問題。我還有其他的代碼,我去了二進制文件,可以在合理的時間內存儲和讀取16000x16000雙精度數組。 – Mephisto

+1

但是,您將ASCII文件讀取爲派生類型可能適用於未格式化的文件。例如,讀取整數分量,然後讀取真實分量,等等。如果遇到問題,請提出其他問題。 – Ross