Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [General] Почему переполнение стека в IFC?! 
:(
    Опции темы
popovda
Дата 25.12.2007, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 290
Регистрация: 9.6.2006
Где: Москва

Репутация: нет
Всего: 6



Попросили тут простенькую прогу накидать на Фортране - для решения ДУ Бюргерса (с пересчетом по правилу Рунге):
Код

! Решить урмат: U_t = U_xx + (exp(x^3)-1) в "стакане"
! U(0,x) = 0,
! U(t,0) = U(t,1)=0
! используюя следующий шаблон
!        o
!        |
!      o-o-o, схема явная, устойчива при соотношении 
!шагов h_t~h_x^2.
! Точность eps = 1e-4;

program Ex_2
implicit none;

! Размеры сетки по x и t - Mx подобран минимально путем нескольких запусков. 
! Динамически решить задачу не удалось, т.к. сетка очень большая и 
! превышает размер стека
integer(4), parameter :: Mx=100;
integer(4), parameter :: Mt=5*Mx*Mx;

! Точность
real(8), parameter :: eps = 0.0001_8; ! Что именно 8 байт в типе.

! Дескриптор файла вывода 
integer(4), parameter :: f_out = 1001;
! Счетчики
integer(4) :: m,n;
! Сетки для пересчета и невязка
real(8) , allocatable, dimension(:,:) :: U1, U2, R;
! И переменная максимума невязки
real(8) :: max_R;




allocate(U1(0:Mt,0:Mx), U2(0:2*Mt,0:2*Mx), R(1:Mt,1:Mx-1));

! Первый раз вычисляем ДУ
U1 = DU(Mt,Mx);

! Проверим точность
U2 = DU(2*Mt, 2*Mx);
    
forall( m = 1:Mx-1, n = 1:Mt) 
    R(n,m) = abs(U2(2*n,2*m) - U1(n,m));
end forall;
    
! Т.к. схема 1-го порядка,то 
! max(U2 - U1)<(2*r - 1)*eps == eps
max_R = maxval(R);
print *,' max(R) = ',max_R;
if( max_R < eps) then
    print *,'Answer in file Result.csv';
    
    ! Вычислили, теперь выводим результат
    open(f_out,file='Result.csv',status='replace');
    do n = 0,Mt
        write(f_out,"( <2*Mx+1>(f15.8,';') )") U2(n,:);
    end do;
    close(f_out,status='keep');
else
    print *,'Grid so small';
end if;


deallocate(U1, U2, R);

write(*,*) 'press enter';
read(*,*);
contains
! Конечно-разностная реализация
function DU(Mt,Mx) result(U)
    ! На вход 
    ! Размеры сетки по t и x
    integer(4), intent(in) :: Mt, Mx;
    
    ! На выход
    ! Сама сетка - в строке - t, в столбце x!
    real(8), dimension(0:Mt,0:Mx) :: U;
    
    ! Внутренние переменные --------------------------------
    ! Вспом. сетка для f(x) = exp(x**3+1)
    real(8), dimension(0:Mx) :: f;
    ! Счетчики
    integer(4) :: m,n;
    ! Шаги
    real(8) :: ht; 
    real(8) :: hx; 
    
    
    !------------ Тело функции ------------------------------
    ! Вычисляем шаги
    ht = (1.0-0.0)/dble(Mt);
    hx = (1.0-0.0)/dble(Mx);
    
    ! К О Д      П Р О Г Р А М М Ы
    U = dble(0.0); 
    ! Т.к. На границах у нас везде нули, то мы задали ГУ.
    ! Вспом. функция, чтобы не вычислять постоянно
    forall(m=0:Mx) f(m) = exp((m*hx)**3 - 1.0);

    !write(*,*) 'Size of grid (T,X) = (',N ,',', M, ')';

    do n = 0,Mt-1
        do m = 1,Mx-1 ! Только по внутренним точкам сетки, чтобы не портить ГУ
            if(m==0 .or. m==Mx) print *,'Error!!!';
            
            U(n+1,m) = ht/(hx**2)*( U(n,m+1) - 2*U(n,m) + U(n,m-1) ) + &
                   ht*f(m) + U(n,m);
        end do; ! m
    end do ! n
end function DU;
end program Ex_2;


Ну код вроде понятный. Так вот. Я привык писать в стиле Ф95/HPF/03, поэтому использовал не процедуру, а функцию, возвращающую массив (кстати, такая конструкция с точки зрения стандарта предпочтительнее). Переполнение стека. (Stack overflow)

Но, я изменил в Project->Properties->Link->System->Stack Commite size до ГАРАНТИРОВАННЫХ 256 мб.
(Это то же, что опция /STACK:nnnnn). А ему мало. Если организовать вызов не функции, а процедуры, то все равно при попытке организовать полноценный пересчет при перераспределении памяти для U1 и U2 наступает переполнение. Компилятор IFC 9.1.028. В чем дело?!


--------------------
С уважением, Попов Д.А.
PM MAIL   Вверх
Cr@$h
Дата 4.1.2008, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Дима, привет. Попробуй размещаемые массивы в фунции спользовать: allocatable. Про Stack Commite size в 256 Мб я не уверен. Разве прогам под винды разрешено иметь такой стек? Не связывайся ты с этим стеком. Попробуй динамически размещать память. Кстати, а чем предпочтительнее оформлять как функцию, не как процедуру? Ведь при присвивании Ux = DU идёт копирование элементов результата в матрицу U1, когда как при сall DU(Mx, My, Ux) такого не будет. Обе процедуры будут чистыми, т.к. возвращают один результат. Странно, что при организации как процедуры тоже не работает, но там ведь не со стеком дело?..
PM MAIL ICQ   Вверх
popovda
Дата 5.1.2008, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 290
Регистрация: 9.6.2006
Где: Москва

Репутация: нет
Всего: 6



Как ни пробовал! Проблема в том, что должен быть выделен большой ДИНАМИЧЕСКИЙ массив. И выяснилось следующее - как только я пытаюсь создать такой массив - либо в основной программе, либо в подпрограмме, то массив пытается разместиться, но банально не хватает памяти. Ваш вариант тоже пробовал - тот же результат: во время выполнения переполнение стека и рекомендация увеличить размер, при 2 Гб ОЗУ на компе. Банально, но когда столкнулся с такой же хреновиной года 2 назад под CVF - изменение размера стека спасло. Дал директивно 200 мб и все.... Что до чистых процедур/функций. Я понимаю, что может возникать фрагментация памяти. Поэтому я давно поставил с десяток экспериментов - фрагментация есть только в дебаге, т.е. при отключенной оптимизации. Как только включена оптимизация хотя бы по памяти, то проблем с фрагментацией памяти нет. Да и в принципе разница между объявлениями
function FuncName(...tra-ta-ta...) result(res)
и
subroutine FuncName(...tra-ta-ta...,res) для компилятора (с оптимизацией!!!) нет - все равно массив возвращается через адрес 1-го элемента. А про хитрости с оптимизацией я указал. Кстати, на NAG Fortran 5.1 код запахал без проблем... А вот читабельность кода выше.
Что до чистых подпрограмм, то чистая процедура и чистая функция пришли из HPF, как и конструкция 
furnctoin ... result(res) - именно с целью высокой оптимизации в модели общей памяти для чистых подпрограмм.  




--------------------
С уважением, Попов Д.А.
PM MAIL   Вверх
Cr@$h
Дата 8.1.2008, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Но стек не может переполняться, когда работаешь с динамическим размещением памяти. Работать будет, если внутри процедуры (подпрограммы или функции) убрать статические объявление real(8), dimension(0:Mt,0:Mx) :: U И результат функции можно сделать allocatable, тогда в стеке вообще ничего не будет практически. Плюс в головной программе поставить allocatable. но больше двух гигов в виндах просто так не выделить точно.

На счёт чистоты. Бог с ней. Есть чистые подпрограммы и функции. Меня фрагментация интересует больше.

ArrayA = Func(ArrayB, ArrayC)
call Func(ArrayA, ArrayB, ArrayC)
Чем ДОЛЖНЫ отличаться эти два варианта. В первом случае выделяется динамически память для результата функции и потом эти значения копируются в ArrayA, который должен быть уже размещён или быть allocatable. После память освобождается. Во втором случае значения результата сразу заносятся в массив ArrayA, память не выделяется. Сводится ли это к одному и тому же коду при оптимизации, мне неизвестно? К тому же, это модельный пример, что делать со сложными ситуациями. Вернее, что делает с ними компилятор.

P.S. И откуда это у фортраниста точки с запятой в конце строк? smile
PM MAIL ICQ   Вверх
Иванофф
Дата 9.1.2008, 00:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 8.9.2006

Репутация: нет
Всего: нет



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

немного удивляет тема обсуждения и состав участников, или первое или второе должно быть другим  smile 
PM MAIL   Вверх
popovda
Дата 19.1.2008, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 290
Регистрация: 9.6.2006
Где: Москва

Репутация: нет
Всего: 6



Вот. Я на эту тему
Цитата

ArrayA = Func(ArrayB, ArrayC)
call Func(ArrayA, ArrayB, ArrayC)

Чем ДОЛЖНЫ отличаться эти два варианта.


Интересовался у многих специалистов, таких как Серебряков или Горелик, так вот они однозначно сообщили, что если это нормально написанный компилятор, то такой синтаксис возвращаемого аргумента (через result) в функции как раз и предназначен для ОПТИМИЗАЦИИ по памяти. То есть указанные выше вызовы фактически эквивалентны. Фрагментации на мониторе памяти не наблюдалось.
А про ";" в конце - привычка - я на первом курсе на Паскале писал, а потом со второго и по н.в. на C/С++. Просто у меня глаз режет, если ; не стоит. Психологически не воспринимаю код.

Что до 
Код

function DU(Mt,Mx) result(U)
    ! На вход 
    ! Размеры сетки по t и x
    integer(4), intent(in) :: Mt, Mx;
    
    ! На выход
    ! Сама сетка - в строке - t, в столбце x!
    real(8), dimension(0:Mt,0:Mx) :: U;

то U - это автоматический массив. Не статический.

Это сообщение отредактировал(а) popovda - 19.1.2008, 22:47


--------------------
С уважением, Попов Д.А.
PM MAIL   Вверх
Cr@$h
Дата 18.1.2009, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Цитата(popovda @  19.1.2008,  23:45 Найти цитируемый пост)
такой синтаксис возвращаемого аргумента (через result) в функции как раз и предназначен для ОПТИМИЗАЦИИ по памяти

Почему этот синтаксис ведёт к оптимизации, чем отличается от функции без reult и от чистой процедуры?

Кстати, добил эту реализацию?
Цитата(popovda @  19.1.2008,  23:45 Найти цитируемый пост)
то U - это автоматический массив. Не статический.

Хм.. Его размер известен на этапе компиляции. Может память выделяется статическая?
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Fortran | Следующая тема »


 




[ Время генерации скрипта: 0.0462 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.