Введение в программирование больших вычислительных задач на современном Фортране с использованием компиляторов Intel

Файлы

Показывать лекцию целиком

Вы можете скачать презентацию к данной лекции здесь.

Назначение файлов

Исходные данные

Промежуточные вычисления

Результаты вычислений

Конвертация данных

Обмен данными с другими программами

Внешние и внутренние файлы

Внешний файл - именновання область на внешнем носителе.

C:\docum.inf

D:\DATA\results.txt

E:\geometry.dat

Внутренний файл – символьная строка или массив.

character(100) buffer

characrer(1000) temp(10)

Файловые записи

Запись – единица обмена данными между программой и внешней памятью.

Расположены в файле последовательно.

Форматные записи внутреннее → внешнее представление

Неформатные записи внутреннее представление

Запись конец файла последняя запись в файле.

Форматные файлы

Содержат форматные записи.

Каждая запись оканчивается управляющими символами (возврат каретки, перевод строки).

Возможность "ручного" редактирования.

Скорость обработки файлов низкая.

Больший объём файлов.

Внешние и внутренние файлы.

Неформатные файлы

Содержат неформатные записи.

Отсутствует возможность "ручного" редактирования.

Скорость обработки файлов высокая.

Меньший объём файлов.

Внешние файлы.

Двоичные файлы

Содержат данные в двоичном представлении.

Длина записи равна 1 байту.

Отсутствует возможность "ручного" редактирования.

Эффективны для хранения больших объёмов данных (хранение промежуточных вычислений).

Внешние файлы.

Последовательный доступ

Доступ к данным по порядку

Записи переменной длины

Добавление новой записи - в конец файла

Прямой доступ

Доступ к данным произвольный

Записи одинаковой длины

Внешний файл может быть прямого и последовательного доступа

Внутренний файл только последовательного доступа

Оператор Open

open (unit = u ,

file = name ,

err = label ,

iostat= i-var ,

...)

Создает устройство ввода/вывода с номером u и подсоединяет к нему внешний файл name.

open (unit = 1, file = "data.txt")

open (unit = 2, file = "D:\DOCUM\price.inf")

Параметры оператора Open

uint - номер устройства

file – имя файла

err - метка на оператор обработки ошибки

iostat – номер ошибки (0 – отсутствие).

... – один или несколько спецификаторов ( ≈ 40 )

Спецификаторы
ACCESS ENCODING RECORDSIZE
ACTION FORM RECORDTYPE
ASSOCIATEVARIABLE IOFOCUS ROUND
ASYNCHRONOUS MAXREC SHARE
BLANK MODE SHARED
BLOCKSIZE NAME SIGN
BUFFERCOUNT NEWUNIT STATUS
BUFFERED NOSHARED TITLE
CARRIAGECONTROL ORGANIZATION TYPE
CONVERT PAD USEROPEN
DECIMAL POSITION
DEFAULTFILE READONLY
DELIM RECL
DISPOSE

Примеры оператора Open

! двоичный файл
open(1,file = "backup.bin",form = 'binary')

! добавление записей в конец файла
open(2,file = "history.txt",access = 'append')

! только для чтения
open(3,file = "data.txt", action = 'read')

! файл должен существовать 
open(4,file = "geometry.dat", status = 'old')

! асинхронный ввод/вывод 
open(5,file = "tornado.dat", asynchronous = 'yes')

! файл доступен другим приложениям
open(6,file = "base.dat", share = 'denynone') 

! файл недоступен другим приложениям 
open(7,file = "base2.dat", share = 'denyrw')

Файловый ввод/вывод

Оператор read – чтение данных из файла

Последовательный доступ

форматные:

read(unit, format, ...)

неформатные:

read(unit, ...)

Прямой доступ

форматные:

read(unit, format, rec, ...)

неформатные:

read(unit, rec, ...)

Внутренние файлы

read(unit, format, ...)

Ввод/вывод в файлы

Оператор write – запись данных в файл

Последовательный доступ

форматные:

write(unit, format, ...)

неформатные:

write(unit, ...)

Прямой доступ

форматные:

write(unit, format, rec, ...)

неформатные:

write(unit, rec, ...)

Внутренние файлы

write(unit, format, ...)

Примеры

! ЗАПИСЬ ДАННЫХ ВО ВНТУРЕННИЙ ФАЙЛ

program buffer
  character(20) buf
  integer(4) a,b,c,d

  !----- читаем формулу в символьную строку
  write(*,"(A,\)") "Enter expression......."
  read(*,"(A)") buf ! во внутренний файл

  !-------- заменяем все плюсы на пробелы
  do k = 1,len(buf)
    if (buf(k:k) == '+') buf(k:k) = ' '
  end do

  read(buf,*) a,b,c,d
  
  write(*,*) a+b+c+d

  end

Примеры

! ЗАПИСЬ ДАННЫХ ВО ВНЕШНИЙ ФАЙЛ ПОСЛЕДОВАТЕЛЬНОГО ДОСТУПА

program buffer
  character(20) buf
  integer(4) a,b,c,d

  !----- читаем формулу в символьную строку
  write(*,"(A,\)") "Enter expression......."
  read(*,"(A)") buf ! во внутренний файл

  !-------- заменяем все плюсы на пробелы
  do k = 1,len(buf)
    if (buf(k:k) == '+') buf(k:k) = ' '
  end do

  read(buf,*) a,b,c,d
  
  write(*,*) a+b+c+d

  end

Примеры

! ЗАПИСЬ ДАННЫХ ВО ВНЕШНИЙ ФАЙЛ ПРЯМОГО ДОСТУПА
program random_file
real x
integer :: k = 0
  open (1, file = "C:\numbers.txt", access = 'direct', 
           recl = 10, form = 'formatted')
  do 
    call random_number(x)
    k = k+1
    x = x-0.78
    write(1,"(f10.4)", rec = k) x
    if (abs(x)<0.0001) exit
  end do  
  write(1,"(i10)", rec = 1) k
  close(1)
  end

Данные записанные в файл

4644   -0.7545   -0.4275   -0.1131    0.1831    0.0583...

Оператор Backspace

Перемещает файловый указатель на одну запись назад в файлах последовательного доступа.

backspace (unit = u , err = label , iostat = i-var)

backspace(1)

backspace(2, err = 200)

backspace(3, err = 200, iostat = ios)

Оператор Rewind

Перемещает файловый указатель в начало первой записи.

rewind (unit = u , err = label , iostat = i-var)

rewind(1)

rewind(2, err = 200)

rewind(3, err = 200, iostat = ios)

Функция EOF

Возвращает .TRUE. если файловый указатель установлен на запись "конец файла". В противном случае результат .FALSE.

Часто используется для чтения всех данных из файла

do while ( .NOT.eof(1) )
  read(1,*) param
  ...
end do

Пример:

program read_file
real(4), allocatable :: A(:)
real(4) AT
integer(8) :: k = 0

open(1,file = "C:\data.txt")
do while (.NOT.EOF(1)) ! подсчёт элементов массива
  read(1,*)  AT
  k = k+1
end do
allocate(A(k)) ! размещение массива

rewind(1) 
k = 1
do while (.NOT.EOF(1)) ! чтение элементов массива
  read(1,*)  A(k)
  k = k+1
end do
end

Оператор Inquire

INQUIRE (FILE=name, ERR=label, ID=idvar, IOMSG=msgvar, SIZE=sz, IOSTAT=ivar, DEFAULTFILE=def, slist)

INQUIRE (UNIT=iounit, ERR=label, ID=idvar, IOMSG=msgvar, SIZE=sz, IOSTAT=ivar, slist)

INQUIRE (DIRECTORY=dir, EXIST=ex, DIRSPEC=dirspec, ERR=label, ID=idvar, IOMSG=msgvar, SIZE=sz, IOSTAT=ivar)

INQUIRE (IOLENGTH=len) out_item_list

Пример:

program inquire_list ! ***** Вычисление размера списка вывода
real(8) A(100)
complex(16) S(20)
integer ioL

inquire(iolength = ioL) A,S,B   ! размер списка вывода = 361

end
program if_exist ! ***** Проверка существования файла
character(100) fname
logical exists
 
write (*, *) 'Enter the file name: '
read (*, '(a)') fname
 
inquire (file = fname, exist = exists)
 
if (.not. exists) write (*,'(2a/)') 'Cannot find ', fname
end

Оператор Close

Отсоединяет файл от устройства ввода/вывода и закрывает это устройство

close (unit = u , err = label , iostat = ivar , status = stat)

status – символьное выражение принимающее значения: keep или delete

program delete_file ! ***** Удаление файла
  open(1,file = "C:\data.txt")
  read(1,*) a,b,c
  close(1,status = 'delete')
end

Асинхронный ввод/вывод

Параллельное выполнение файлового ввода/вывода и других операторов программы.

Спецификатор asynchronous='yes' в операторах open, write, read.

open (1, asynchronous = 'YES')

! синхронный вывод:

write(1,*, asynchronous = 'NO') A, B, C

! асинхронный вывод:

write(1,*, asynchronous = 'YES') D, E, F

Переменные участвующие в асинхронном вводе/выводе получают атрибут asynchronous.

Явное задание атрибута при объявлении.

real, asynchronous :: MS, NV

complex, asynchronous :: TN(100,100)

Оператор wait ожидает окончание асинхронной работы с файлом.

Неаккуратное использование асинхронной работы с файлом может приводить к гонкам данных.

Содержимое файла C:\AS.txt содержит разные данные !

...    
   9.000000       9.000000       9.000000       9.000000
   9.000000       9.000000       9.000000       9.000000
   9.000000       9.000000       9.000000       9.000000
   9.000000       9.000000       9.000000       9.000000
   9.000000       9.000000       9.000000       10.00000
   10.00000       10.00000       10.00000       10.00000
   10.00000       10.00000       10.00000       10.00000
   10.00000       10.00000       10.00000       10.00000
   10.00000       10.00000       10.00000       10.00000
   10.00000       10.00000       10.00000       10.00000
   ...

Анализ программы asyn_data_races с помощью Intel Inspector XE 2011 указывает на гонки данных в программе.

Используем оператор wait, чтобы дождаться завершения записи данных в файл.

program asyn_data_races

  real(4) :: A(100,100) = 1.0
   
  open(1,file = "C:\AS.txt", asynchronous = 'YES')
  
  do k = 1,10
    rewind(1)
    write (1,*,asynchronous = 'YES') A
    wait(1) ! дожидаемся, когда завершится поток, 
            ! отвечающий за запись данных в файл
    A = real(k)
  end do
  close(1)
end

Оператор Flush

Сброс логических буферов при буферизованном выводе

program prog
integer, parameter :: N = 100
real A(N)
  open(1, buffered = 'yes', file = 'dat')
  write(1, *) A
  flush(1) 

  call C_subroutine('dat') ! читает данные из файла dat
! ----- некоторый код
end

При буферизации, логически записанные данные могут физически не успеть попасть на диск, что вызовет ошибку чтения данных.

Процедуры модуля ifport

ACCESS Определение доступа к файлу
CHANGEDIRQQ Установка директории текущей
CHANGEDRIVEQQ Установка диска текущим
CHDIR Смена рабочей директории
CHMOD Смена атрибутов файла
DELDIRQQ Удаление директории
DELFILESQQ Удаление файлов
FINDFILEQQ Поиск файлов
FULLPATHQQ Полное имя файла или директории
GETDRIVEDIRQQ Путь текущей рабочей директории
GETDRIVESIZEQQ Размер текущего диска и доступного пространства
GETDRIVESQQ Имена имеющихся дисков
GETFILEINFOQQ Информация о файле
PACKTIMEQQ Упаковывает время для использования в SETFILETIMEQQ
RENAMEFILEQQ Переименование файла
SETFILEACCESSQQ Способ доступа к файлу
SETFILETIMEQQ Установка даты изменения файла
SPLITPATHQQ Выделяет в полном имени 4 компоненты файла (диск, папки, имя, расширение)
UNPACKTIMEQQ Распаковка упакованного времени

* З а д а н и е *

Промежуточное сохранение вычислений. В программе save_results организовать промежуточное автосохранение массива A через каждые auto итераций в файл numerical.save.

Предусмотреть:

  • возможность продолжения вычислений при повторном запуске программы;
  • обработку ошибок;
  • *Задание*

    program SAVE_DATA
    use ifport
    implicit none
    integer, parameter :: M = 150 
    real(16) A(M,M,M), B(M,M,M), C(M,M,M) 
    integer, parameter :: N = 1000  ! кол-во итераций
    integer i,j,k,it
    do it = 1,N
      write(*,*) "Current iteration = ",it
      call random_number(A)
      call random_number(B)
      call random_number(C)
      do i = 1,M
      do j = 1,M
      do k = 1,M
        A(i,j,k) = exp(B(k,j,i))*cos(C(j,k,i)**A(i,k,j))
      end do
      end do
      end do
    end do
    END
    

    * Вариант программы *

    program save_data
    use ifport
    implicit none
    
    integer, parameter :: M=150 
    real(16) A(M,M,M), B(M,M,M), C(M,M,M) 
    integer, parameter :: N = 1000  ! кол-во итераций
    
    character(20) ::    name = 'C:\numerical.save',  ! файл автосохранения
                     tmpname = 'C:\numerical.tmp'     ! файл временной копии
    
    integer, parameter :: auto = 10 ! интервал автосохранения
    integer i,j,k,it, itstart, ires
    logical ex, ext
    
    inquire(file=name,    exist = ex)  
    inquire(file=tmpname, exist = ext) 
    
    if (.NOT. ex) then ! если нет файла автосохранения
      if (.NOT. ext) then ! если нет временной копии
        write(*,*) "No data saved. Starting at iteration = 1"  ! 1) тогда новый  расчет
        itstart=1
      else
        open(1,file=tmpname, status='OLD', form='binary') ! 2) иначе данные могут быть во временой копии
        read(1, ERR=100, END=101) itstart, A 
        write(*,*) "Data was saved at iteration = ", itstart
        close(1)
      end if
    else
      write(*,*) "Reading saved data from file....." ! 3) данные могут быть в файле автосохранения
      open(1,file=name, status='OLD', form='binary')
      read(1, ERR=100, END=101) itstart, A
      close(1)
      if (ext) then ! 4) если есть файл и временная копия
        write(*,*) "Finding more than one copy. Deleted..."
        ires=DelFilesQQ(tmpname) 
      end if
    end if
    
    

    * Вариант программы *

    do it=itstart,N
      write(*,*) "Current iteration = ",it
    
      if (mod(it,auto)==0) then   ! автосохранение промежуточных вычислений
        open(2, file=tmpname, form='binary') ! сначала сохраняем во временный файл
        write(2,ERR=102) it, A
        close(2)
        ires=DelFilesQQ(name) ! удаляем предыдущий файл автосохранения
        ires=RenameFileQQ (tmpname, name) ! файлом автосохранения становится временная копия
        write(*,*) "Data succesfully saved at iteration = ", it
      end if
    
      call random_number(A)
      call random_number(B)
      call random_number(C)
    
      do i=1,M
      do j=1,M
      do k=1,M
        A(i,j,k)=exp(B(k,j,i))*cos(C(j,k,i)**A(i,k,j))
      end do
      end do
      end do
    
    end do
    stop
    
    ! ----- обработка ошибок ------
    100 stop "Error while reading data file !"
    101 stop "End of data file encountered !"
    102 stop "Error while writing data file !"
    
    END
    
    
    
    Вернуться к учебному плану