2017-02-20 3 views
3

Я разрабатываю код со скомпилированным языком (Fortran 95), который выполняет определенные вычисления в огромном каталоге галактик. Каждый раз, когда я реализую некоторые изменения, я компилирую и запускаю код, и требуется около 3 минут, просто читая ASCII-файл с данными галактики с диска. Это пустая трата времени.Уловка для чтения данных с жесткого диска быстрее между сложными компиляциями

Если бы я начал этот проект в IDL или Matlab, тогда это было бы иначе, потому что переменные, содержащие данные массива, сохранялись бы в памяти между различными компиляциями.

Однако, я думаю, что можно что-то сделать, чтобы ускорить это отвращение чтения с диска, например, наличие файлов в поддельном разделе RAM или что-то в этом роде.

+0

Я немного изменил заголовок, чтобы лучше подобрать ответ, который я выбрал. Этот ответ не соответствует моему первоначальному ответу 100% (нет подсказок о том, как сделать раздел в ОЗУ), но слишком полезно не присуждать ему зеленый тег. Я напишу еще один вопрос о каталоге RAM. – Mephisto

+1

Вы сделали некоторые фактические измерения, или вы просто догадываетесь, что узким местом является дисковый ввод-вывод, а не, например, анализ формата данных ASCII? Предполагая, что у вас достаточно RAM для ramdisk, у вас, вероятно, также есть много доступного для дискового кеша, поэтому есть хорошие шансы, что вы все равно читаете в основном из памяти. Принятый ответ намекает на это. –

+0

@ DanMašek Я игнорирую особенности того, что вы предлагаете, но я думаю, что это происходит в первый раз, когда я запускаю код после входа в систему, чем последовательные чтения. Кроме того, пока файл читает, команда TOP не показывает 100% -ную активность процессора, поэтому, вероятно, проблема связана с чтением жесткого диска. – 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-й столбец - это символ, второй - целое число, другие столбцы - с плавающей запятой ...), и я определил производный тип. Я не уверен, как справиться с этим при записи двоичного файла. У меня есть и другие коды, где я отправился в двоичный файл, чтобы хранить и считывать массивы с двойной точностью 16000x16000 в разумные сроки. – Mephisto

+1

Однако вы читали файл ASCII в производном типе, скорее всего, работаете с неформатированным файлом. Например, прочитайте целочисленные компоненты, затем реальные компоненты и т. Д. Если у вас есть проблемы, задайте другой вопрос. – Ross

Смежные вопросы