2016-03-11 1 views
1

Из-за проблем с производительностью при передаче кода из статического в динамическое распределение я начал походить о том, как управление памятью управляется в коде Fortran.Является ли порядок или синтаксис выражения allocate влиять на производительность? (Fortran)

В частности, в этом вопросе я блуждаю, если порядок или синтаксис, используемые для оператора allocate, имеют значение. То есть, он делает никакой разницы для выделения векторов, таких как:

allocate(x(DIM),y(DIM)) 

против

allocate(x(DIM)) 
allocate(y(DIM)) 

Синтаксис предполагает, что в первом случае программа будет выделять все пространство для векторов сразу, возможно, улучшая производительность, а во втором случае он должен выделять пространство для одного вектора за раз, чтобы они могли оказаться далеко друг от друга. Если нет, то есть, если синтаксис не имеет никакого значения, я блуждаю, если есть способ контролировать это распределение (например, выделение вектора для всего пространства и использование указателей для адреса пространства, выделенного в виде нескольких переменных).

Наконец, я замечаю, что я даже не знаю одного: выражение allocate гарантирует, что хотя бы один вектор занимает смежное пространство в памяти (или, что самое лучшее, что может?).

+0

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

+2

Этот ответ - http://stackoverflow.com/questions/13308684/increase-of-virtual-memory-without-increse-of-vmsize/13309395#13309395 - и другие расскажут вам, что в системах Linux по крайней мере , 'allocate' вряд ли вызовет выделение памяти, он будет интерпретироваться скорее как уведомление o/s, чтобы получить больше памяти. Затем, когда вы пишете свежеопределенную память, вещи действительно начинают происходить. Как это влияет на производительность вашего кода, я не знаю. Но мне было бы интересно прочитать ваши отчеты о ваших экспериментах, чтобы узнать. –

+0

Также http://stackoverflow.com/questions/11335108/fortran-allocate-deallocate, –

ответ

2

С языка стандартная точка зрения в обоих направлениях, как их можно записать. Компилятор может свободно распределять массивы там, где они хотят. Обычно он вызывает malloc() для выделения некоторого фрагмента памяти и делает выделенные массивы из этой части.

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

Я просто подтвердил, что мой gfortran просто вызывает __builtin_malloc два раза в этом случае.

Еще одна проблема уже отмечена знаком высокой эффективности. Даже когда malloc() успешно возвращается, фактические страницы памяти все еще не могут быть назначены. В Linux это происходит при первом доступе к массиву.

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

Есть ли способ контролировать распределение? Да, вы можете перегрузить malloc своим собственным распределителем, который делает некоторые умные вещи. Он может использоваться для того, чтобы память всегда соответствовала 32-байтам или аналогичным целям (example). Будете ли вы улучшать производительность вашего кода, выделяя вещи, как-то близкие друг к другу, сомнительны, но вы можете попробовать. (Конечно, это полностью зависит от компилятора, компилятор не должен использовать malloc() вообще, но в основном они делают.) К сожалению, это будет работать только тогда, когда вызовы malloc не включены.

2

Здесь есть (по крайней мере) две проблемы, во-первых, время, затрачиваемое на выделение памяти, а во-вторых, местоположение памяти в массивах и влияние этого на производительность. Я не знаю много о фактическом процессе распределения, хотя ссылки, предложенные High Performance Mark, и ответ Вадимира F охватывают это.

С вашего вопроса кажется, что вас больше интересуют хиты кеша и локальность памяти, заданные массивами, находящимися рядом друг с другом.Я бы предположил, что нет никакой гарантии, что оператор allocate обеспечивает обе массивы рядом друг с другом в памяти. Это основано на выделении массивов в типе, который в ФОРТРАН 2003 MAY 2004 WORKING DRAFT J3/04-007 standard

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

Из обсуждения с Vadimir F, если вы помещаете распределяемые массивы в тип и используете ключевое слово sequence, например.

type botharrays 
    SEQUENCE 
    double precision, dimension(:), allocatable :: x, y 
end type 

Это НЕ гарантирует, что они выделены как смежные в памяти. Для статических массивов или множества переменных последовательный тип звучит так, как будто он может работать как ваша идея «выделения вектора для всего пространства и использования указателей для адреса пространства, выделенного в виде нескольких переменных». Я думаю, что общие блоки (Fortran 77) позволили вам указать связь между расположением памяти массивов и переменными в памяти, но не работают с распределяемыми массивами.

Короче говоря, я думаю, это означает, что вы не можете обеспечить, чтобы в памяти находились два выделенных массива. Даже если бы вы могли, я не понимаю, как это приведет к сокращению промахов в кеше или повышению производительности. Даже если вы обычно используете эти два вместе, если массивы не являются достаточно маленькими, чтобы кэш включал несколько массивов в один прочитанный (при условии, что чтение позволяет выйти за пределы массива), вы не будете использовать местность памяти.

+0

Я уверен, что 'SEQUENCE' либо не относится к выделенным и указательным компонентам, либо вообще не допускается для такой структуры. В любом случае это рецепт проблем, поскольку он отключает заполнение внутри структуры, что может быть очень полезно для производительности. –

+0

Разрешено, но я на 100% уверен, что он не влияет на распределяемые и указательные компоненты (просто проверил полученный код, не успел обыскать в стандарте). –

+0

А я не знал, что 'sequence' не работает для распределяемых массивов, я не вижу ничего в стандарте, чтобы сказать в любом случае, хотя он говорит:« Тип - это «тип числовой последовательности», если есть нет параметров типа, нет указателей или распределяемых компонентов ». Я предполагаю, что это подразумевает, что переменная типа переменной применяется только без выделяемых компонентов. –