У меня есть размещаемый массив определенного пользователем типа.Размер массива и значения элементов массива должны быть считаны из файла.У меня есть серийный код, который выглядит примерно так:
MODULE read_and_allocate
IMPLICIT NONE
TYPE my_type
INTEGER :: my_number
CHARACTER(10) :: my_string
CONTAINS
PROCEDURE :: read_my_type_from_string_array
PROCEDURE :: write_my_type
GENERIC :: WRITE(formatted) => write_my_type
END TYPE my_type
TYPE(my_type), ALLOCATABLE :: my_array(:)
CONTAINS
SUBROUTINE read_my_type_from_string_array(var, string_array)
CLASS(my_type), INTENT(INOUT) :: var
CHARACTER(*), INTENT(IN) :: string_array(:)
!code omitted
END SUBROUTINE read_my_type_from_string_array
SUBROUTINE write_my_type(var, funit, iotype, v_list, iostat, iomsg)
!code omitted
END SUBROUTINE write_my_type
SUBROUTINE read_my_array(var, funit)!, iotype, v_list, iostat, iomsg)
TYPE(my_type), ALLOCATABLE, INTENT(INOUT) :: var(:)
INTEGER, INTENT(IN) :: funit
CHARACTER(200) :: line
INTEGER :: rec_count, rec_len, max_rec_len
LOGICAL :: in_rec
INTEGER :: pos
CHARACTER(200),ALLOCATABLE :: rec(:)
INTEGER :: ii, jj
INTEGER :: status
! calling read_my_array deallocates var
IF (ALLOCATED(var)) DEALLOCATE(var)
max_rec_len = 0
rec_count = 0
in_rec = .FALSE.
DO
READ(funit, '(a)', iostat=status) line
IF (status < 0) EXIT
IF (in_rec .AND. TRIM(ADJUSTL(line)) == ']') THEN
in_rec = .FALSE.
END IF
IF (in_rec) THEN
rec_len = rec_len+1
END IF
IF (.NOT. in_rec .AND. TRIM(ADJUSTL(line)) == '[my_type') THEN
in_rec = .TRUE.
max_rec_len = MAX(max_rec_len, rec_len)
rec_len = 0
rec_count = rec_count + 1
END IF
END DO
ALLOCATE(rec(max_rec_len))
ALLOCATE(var(rec_count))
REWIND(funit)
in_rec = .FALSE.
jj = 1
DO
READ(funit, '(a)', iostat=status) line
IF (status < 0) EXIT
IF (in_rec .AND. TRIM(ADJUSTL(line)) == ']') THEN
CALL var(jj)%read_my_type_from_string_array(rec)
jj = jj + 1
in_rec = .FALSE.
END IF
IF (in_rec) THEN
rec(ii) = line
ii = ii+1
END IF
IF (.NOT. in_rec .AND. TRIM(ADJUSTL(line)) == '[my_type') THEN
in_rec = .TRUE.
rec(:) = ''
ii = 1
END IF
END DO
DEALLOCATE(rec)
END SUBROUTINE read_my_array
SUBROUTINE write_my_array(var, funit)
!code omitted
END SUBROUTINE write_my_array
END MODULE read_and_allocate
PROGRAM my_test
USE read_and_allocate
IMPLICIT NONE
INTEGER :: funit
OPEN(newunit=funit, file='input.txt')
CALL read_my_array(my_array, funit) !this routine allocates my_array
CALL write_my_array(my_array, 6)
END PROGRAM my_test
Это работает, как и ожидалось (протестировано с gfortran на Mac).Короче говоря, read_my_array
обрабатывает данный входной файл, выводит необходимый размер (N) my_array
, выделяет 'my_array', а затем вызывает read_my_type_from_string_array
N раз, чтобы заполнить каждый элемент my_array
данными.
Теперь я хочу перенести этот код в существующую параллельную программу, но я не совсем уверен, как это сделать правильно.Я думаю, что у меня есть два варианта, но у меня есть опасения по поводу обоих:
1) Я мог читать текстовый файл только в основном процессе, но после прочтения это , яЯ не уверен, что могу так легко транслировать выделяемый массив.
2) Я мог бы заставить каждый процесс читать текстовый файл отдельно, но я боюсь, что смогу создать какое-то условие гонки (функция read_my_array
использует REWIND
и BACKSPACE
), где разные процессы будут получать разные результаты для my_array
.Я нашел эту ветку форума Intel , где упоминается опция SHARE
для открытия файла - я не совсем уверен, что это то, что я ищу.
Есть лилучший способ, как делать такие вещи?
EDIT :
Пример входного файла будет выглядеть примерно так:
[my_type
my_string = 'one'
my_number = 1
]
[my_type
my_string = 'two'
my_number = 4
]
[my_type
my_string = 'alfred'
my_number = 7
]