2015-09-25 6 views
1

Я только начинаю изучать fortran, и я создал простую программу, реализующую метод Эйлера. Я заметил, что время, используемое петлей do, довольно похоже на, например, ту же программу в Matlab.Запись в файл в Fortran do loop

В моей программе Fortran у меня была запись в файл внутри этого цикла do. Когда я удалил его, скорость резко улучшилась, как и ожидалось. Затем я добавил второй do петлю, где поместить запись и измеряли время, необходимое для обеих петель в сочетании:

open(unit=1, file='data.dat') 
write(1,*) t(1),' ', y(1) 
! Calculating 
call cpu_time(start) 
do i = 2,n 
    t(i) = t(i-1) + dt 
    y(i) = y(i-1) + dt*(t(i-1)*(y(i-1))) 
    !write(1,*) t(i),' ', y(i) 
end do 
call cpu_time(finish) 
print '("Time = ",f7.5," seconds.")',finish-start 
call cpu_time(start) 
do i = 2,n 
    write(1,*) t(i),' ',y(i) 
end do 
call cpu_time(finish) 
print '("Time = ",f7.5," seconds.")',finish-start 

время для данного n бы приблизительно в 10-15 раз больше на последнем цикле do по сравнению к первому.

Итак, мой вопрос в том, есть ли лучший способ записать мои данные в файл?

+0

Если вы хотите этот формат в своем выходном файле, я бы не боялся. – haraldkl

+0

Спасибо. В каком формате он будет быстрее? – ninjacowgirl

+0

Вы можете написать все t сразу и все y сразу. Однако это все равно будет довольно медленным. Форматирование довольно дорогое. Вы быстрее получаете неформатированный ввод-вывод, но тогда вы больше не можете читать файл в виде текстового файла. – haraldkl

ответ

2

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

[email protected] ~ 
$ cat t.f90 
Program test 

    ! Corrected program 

    Implicit None 

    Real, Dimension(1:10) :: t, y 

    Integer :: i 

    Call Random_number(t) 
    Call Random_number(y) 

    Do i = 1, 3 
    Write(*, *) t(i), y(i) 
    End Do 
    Write(*, *) 

    Write(*, '(f0.9, 1x, f0.9)') (t(i), y(i), i = 1, 3) 

    Open(1, file = 'stuff.dat') 
    Write(1, '(f0.9, 1x, f0.9)') (t(i), y(i), i = 1, & 
     Min(Size(t), Size(y))) 

End Program test 

[email protected] ~ 
$ gfortran -O -Wall -Wextra -pedantic -std=f95 t.f90 -o test 

[email protected] ~ 
$ ./test 
    0.997559547  0.217951715  
    0.566824675  0.133160353  
    0.965915322  0.900524497  

.997559547 .217951715 
.566824675 .133160353 
.965915322 .900524497 

[email protected] ~ 
$ head stuff.dat 
.997559547 .217951715 
.566824675 .133160353 
.965915322 .900524497 
.747927666 .386765957 
.367390871 .445482254 
.480636895 .661932170 
.073754251 .016108274 
.005355179 .650854826 
.347081244 .646408796 
.342243791 .322987258 

, поскольку компилятор может быть достаточно умным, чтобы превратить все это в одну транзакцию ввода-вывода вместо многих. Но вы не можете быть уверены. Также, чтобы дать ему больше шансов, если вам не нужны все эти десятичные знаки, соответствующим образом настройте формат.

+0

попробуйте скопировать данные в массив '2,10' и записать это – agentp

+0

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

+0

Почти совершенно не имеет значения: я предлагаю ссылаться на поток * нейтрино * (распад нейтронов с половиной времени 15 минут);) –

1

для полноты я выложу 2d копию массива подход:

integer,dimension(10)::x,y 
integer,allocatable::tmp(:,:) 
integer i 
x=[(i, i=0,9)] 
y=x+42 
allocate(tmp(2,size(x))) 
tmp(1,:)=x 
tmp(2,:)=y 
write(*,'(i0,'','',i0)')tmp 
deallocate(tmp) 
end 
 
0,42 
1,43 
2,44 
3,45 
4,46 
5,47 
6,48 
7,49 
8,50 
9,51 

Если производительность действительно критическая, я бы попробовать оба.

Обратите внимание, что наилучшим подходом может быть просто использование 2d-массива (или производного типа) в первую очередь.

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