2015-06-14 2 views
2

Я создал производный тип для доступа к многомерным массивам. С каждым массивом я связываю имя в массиве nm.Заполнение многомерных массивов

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

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

Я бы оценил некоторые предложения относительно возможных способов заполнения массивов производными типами, если есть люди, у которых есть опыт работы с большими наборами данных.

Type :: Multia 

    Character (Len=65) :: nm(3) 
    Real, Allocatable :: ma(:,:,:) 
    Real, Allocatable :: mb(:,:,:) 
    Real, Allocatable :: mc(:,:,:) 

    Contains 
    Procedure :: set 

End Type Multia 


Subroutine set (m, nm, u, i, j) 

    Class (Multia), Intent (InOut) :: m 
    Character (Len=65) :: nm 
    Real, Intent (In) :: u(:) 
    Integer, Intent (In) :: i, j 

    If (nm .e. (m% nm(1))) Then 
    m% ma(:,i,j) = u 
    Else If (nm .e. (m% nm(2))) Then 
    m% mb(:,i,j) = u 
    Else If (nm .e. (m% nm(3))) Then 
    m% mc(:,i,j) = u 
    End If 

End Subroutine set 
+0

Вы не указываете, как распределяются компоненты, но вы считаете 'move_alloc'? – francescalus

+0

Я использую обычный Allocate (m% ma (la, lb, lc)). Не знал о move_alloc. Интересно, как выполняется освобождение. – Charles

ответ

1

Если ваша забота о дублировании массивов, например, в

m%ma = [...] ! Humongous array 

затем Fortran 2003 предлагает move_alloc присущую, который перемещает выделение (включая значения) из одной переменной в другую.

Subroutine set (m, u, v, w) 
    Class (Multia), Intent (InOut) :: m 
    Real, Intent (InOut), allocatable, dimension(:,:,:) :: u, v, w 

    call move_alloc(u, m%ma) 
    call move_alloc(v, m%mb) 
    call move_alloc(w, m%mc) 
End Subroutine set 

называется что-то вроде

type(Multia) m 
real, dimension(:,:,:), allocatable :: u, v, w 
! ... allocating and setting u, v, w 
call m%set(u, v, w) 
! Components of m now allocated, u, v, w, not allocated 

Из примечаний (в Fortran 2008) о том, что изначальное:

Ожидается, что реализация размещаемых объектов, как правило, включают дескрипторы для поиска выделенное хранилище; MOVE ALLOC можно было бы реализовать, передав содержимое дескриптора для FROM в дескриптор для TO и очистив дескриптор для FROM.

То есть ожидается, что не будет копирование временных данных или массивов.

Это предполагает, что вы не можете просто выделить компоненты m и назначить их напрямую.

+0

Я заполню массив, читая данные из файла, а затем переместите значения в один из массивов в Multia. Да, я беспокоюсь о дублировании массивов, так что я не получаю ситуацию, когда для хранения обоих не хватает физической памяти. И думать об этом, также о неэффективном использовании фактического выделения и копирования. – Charles

+1

Вам нужно будет сделать хотя бы одно выделение (предположим, что у вас есть какая-то форма использования динамической памяти), но 'move_alloc' должен избегать копирования и дублирования, а распределение будет очень дешевым по сравнению с чтением из файла , Вы можете читать из файла непосредственно в компоненты типа «Multia», но это выбор дизайна. Надеемся, что подход здесь дает вам выбор: есть ли у вас отдельный массив для какой-либо формы инкапсуляции. – francescalus

+0

Возможно, также стоит добавить, что этот подход означает, что не должно быть начального/различного распределения для компонентов производного типа. Даже если они были распределены первоначально, они были бы освобождены до перемещения. – francescalus

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