我正在開發具有編譯語言(Fortran 95)的代碼,該編譯語言對大型星系目錄進行了某些計算。每次執行一些更改時,我都會編譯並運行代碼,只需要用磁盤上的星系數據讀取ASCII文件大約需要3分鐘。這是浪費時間。訣竅在成本彙編之間更快地從硬盤中讀取數據
如果我在IDL或Matlab中開始這個項目,那麼它會有所不同,因爲包含數組數據的變量將保存在不同編譯之間的內存中。
但是,我認爲可以做一些事情來加速來自磁盤的令人不安的讀取,例如將文件放在假的RAM分區或其他東西中。
我正在開發具有編譯語言(Fortran 95)的代碼,該編譯語言對大型星系目錄進行了某些計算。每次執行一些更改時,我都會編譯並運行代碼,只需要用磁盤上的星系數據讀取ASCII文件大約需要3分鐘。這是浪費時間。訣竅在成本彙編之間更快地從硬盤中讀取數據
如果我在IDL或Matlab中開始這個項目,那麼它會有所不同,因爲包含數組數據的變量將保存在不同編譯之間的內存中。
但是,我認爲可以做一些事情來加速來自磁盤的令人不安的讀取,例如將文件放在假的RAM分區或其他東西中。
而不是在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的一個因素!
因此,不要考慮其他任何事情,請先切換到二進制文件格式。
當然,還有很多二進制格式更適合複雜的數據,並且比簡單的Fortran二進制文件更具可移植性。其中我建議你考慮HDF5。 –
這是一個非常棒的答案,對很多人來說都很有用(+1),但是原始文件有多種類型(第1列是字符,第2列是整數,其他列是浮點...),我定義了派生類型。編寫二進制文件時,我不確定如何處理這個問題。我還有其他的代碼,我去了二進制文件,可以在合理的時間內存儲和讀取16000x16000雙精度數組。 – Mephisto
但是,您將ASCII文件讀取爲派生類型可能適用於未格式化的文件。例如,讀取整數分量,然後讀取真實分量,等等。如果遇到問題,請提出其他問題。 – Ross
爲了更好地匹配我選擇的答案,我稍微更改了標題。這個答案並不適合我原來的答案100%(沒有關於如何在RAM中做分區的線索),但它不太有用,不會獎勵它的綠色標籤。我將特意發佈有關RAM目錄的另一個問題。 – Mephisto
您是否做了一些實際測量,或者您是否猜測瓶頸是磁盤I/O而不是解析ASCII數據格式?假設你有足夠的RAM用於虛擬硬盤,你可能還有足夠的磁盤緩存可用,所以很可能你已經大部分都是從內存中讀取數據。接受的答案暗示了這一點。 –
@DanMašek我忽略了你提出的具體內容,但是我認爲登錄後第一次執行代碼的時間要比連續讀取的時間長。另外,當文件正在讀取時,TOP命令不會顯示100%的cpu活動,所以可能是硬盤讀取問題。 – Mephisto