Научная статья на тему 'Выбор оптимального размещения многомерных массивов в памяти компьютер'

Выбор оптимального размещения многомерных массивов в памяти компьютер Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
201
33
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
размещение данных / кэш-памятЬ / транспонирование многомерных массивов / placement of data / Cache / multidimensional array transposition

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Полуян Степан Вячеславович

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

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

The aim of this work is to create an algorithm that allows for the compilation phase to find optimal placement of the arrays from the point of view of loading of data in a cache.

Текст научной работы на тему «Выбор оптимального размещения многомерных массивов в памяти компьютер»

УДК 004.074

ВЫБОР ОПТИМАЛЬНОГО РАЗМЕЩЕНИЯ МНОГОМЕРНЫХ МАССИВОВ

В ПАМЯТИ КОМПЬЮТЕРА

© 2010 г. С.В. Полуян

Южный федеральный университет, Southern Federal University,

ул. Мильчакова, 8а, г. Ростов н/Д, 344090, Milchakov St., 8a, Rostov-on-Don, 344090,

dnjme@math.sfedu. ru dnjme@math.sfedu. ru

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

Ключевые слова: размещение данных, кэш-память, транспонирование многомерных массивов.

The aim of this work is to create an algorithm that allows for the compilation phase to find optimal placement of the arrays from the point of view of loading of data in a cache.

Keywords: placement of data, cache, multidimensional array transposition.

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

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

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

В данной работе основное внимание будет уделено размещению данных именно в кэш-памяти компьютера. Базовые идеи оптимального размещения данных в памяти компьютера описаны в [1, 2], а с оптимизацией размещения данных в параллельной памяти можно ознакомиться в [3, 4].

Особенности работы кэш-памяти

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

Программно кэш-память представляет собой совокупность блоков данных фиксированного размера, называемых кэш-линейками, или кэш-строками. Каждая кэш-строка полностью заполняется (выгружается) за один пакетный цикл чтения и всегда заполняется (выгружается) целиком. Адрес 1-го байта кэш-линейки всегда кратен размеру пакетного цикла чтения/записи, т.е. начало кэш-линейки всегда совпадает с началом пакетного цикла (рис. 1).

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

В данной статье речь будет идти о кэше прямого отображения, в котором каждой ячейке оперативной памяти однозначно соответствует ячейка кэш-памяти по следующему правилу:

Рис. 1. Загрузка данных в кэш-память при чтении одной ячейки памяти

NumLine = -

Addr

CacheLineSize

-mod-

CacheSize CacheLineSize

(1)

где - номер кэш-линейки, в которую по-

падут данные, расположенные по адресу Addr в оперативной памяти; CacheLineSize и CacheSize - длина кэш-линейки и размер кэш-памяти.

Его достоинство - быстрый поиск требуемых данных, недостаток - вытеснение данных, адреса которых кратны размеру кэш-памяти (т.е. если выполняется условие Addr(A[il][i2]...[im]) = Addr(B[jl][j2]_[jn]) + +z*CacheSize, где 2 ё2, то данные в кэше будут конфликтовать, и если вытесненные данные понадобятся вновь, то это будет означать кэш-промах, и потребуется их повторная загрузка) (рис. 2).

Память

Рис. 2. Вытеснение ранее загруженных данных

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

Условие оптимального размещения массивов

Под оптимальным размещением многомерных массивов в памяти компьютера будем понимать раз-

мещение, при котором происходит минимальное количество загрузок данных в кэш-память.

Оптимальное размещение многомерных массивов зависит от того, как эти массивы хранятся в памяти компьютера, как они используются в программе [6].

В качестве способа изменения размещения данных будем использовать транспонирование массивов.

Определение. Пусть А - многомерный массив размерности т размера ^х^х...х^х...х^х...х^. Тогда транспонированным массивом по индексам ip и ^ называется такой многомерный массив В размерности т размера N1хN2х...хNqх...хNpх...хNm, что A[i1, i2,..., ip,..., iq,..., у = В^ь i2,..., iq,..., ip,., У, где ^ = =1,., N.

Операция транспонирования заключается в том, что индексы ^ и ^ в исходной матрице меняются местами [7].

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

Рассмотрим набор многомерных массивов A1, A2,..., Am. Пусть Е=(сьс2,...,ст) и П=(юью2,...,ют) -наборы перестановок индексов соответствующих массивов AьA2,...,Am; Се - количество заполнений кэш-линеек при обращении к массивам, полученным из AьA2,...,Am транспонированием в соответствии с перестановками с1,с2,.,ст; СП - количество заполнений кэш-линеек при обращении к массивам, полученным из A1Д2,..., Am транспонированием в соответствии с перестановками юью2,...,ют. Тогда массивы AьA2,...,Am лучше разместить в памяти компьютера транспонированными в соответствии с набором перестановок Е, если СЕ < СП.

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

ПеА

множество всевозможных наборов перестановок индексов соответствующих массивов.

Алгоритм вычисления количества заполнений кэш-линеек

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

Для моделирования доступа к кэш-памяти понадобится список заполнения кэш-строк, в котором будет содержаться информация о том, под какую область памяти занята та или иная строка.

Будем считать, что другие программы не оказывают влияния на кэш-память.

Описание алгоритма. Сначала в списке заполнения кэш-строк помечаем все строки как пустые, а счетчику загрузок данных присваиваем ноль.

Для всех данных в соответствии с порядком их использования определяем номера кэш-строк, в которые

они попадут в процессе выполнения программы. Если данные попадают в строку, помеченную в списке как пустая или заполненную другими данными, то перепомечаем эту строку и увеличиваем счетчик загрузок на единицу.

Конец алгоритма.

Таким образом, для работы алгоритма понадобится определить порядок доступа к данным и вычислить номера кэш-строк, в которые эти данные попадут.

Данные из оперативной памяти размещаются не в произвольном месте кэш-памяти, а в строго определенном. Номер кэш-строки, в которой окажется элемент массива, можно определить с помощью формулы (1), в которой параметры CacheLineSize и CacheS-ize зависят от архитектуры вычислительной машины, а адрес произвольного элемента массива определяется относительно начала размещения массива и смещения.

Определить адрес элемента A[ii][i2]...[im] массива А размерности m размера Ni*N2x...xNm можно с помощью одной из следующих формул: Addr (Ap^fe]... [im ]) = Addr( A[0][0]... [0]) +

m m

+ Z (ij * П Nk ) * SizeOf (TypeData), если j=1 k =j+1

массив хранится в памяти компьютера по строкам; Addr(A[i1][i2]...[im ]) = Addr(A[0][0]... [0]) +

m j—1

+ Z (ij * П Nk ) * SizeOf (TypeData) - по столбцам. j=1 k=1

Эти формулы используются в зависимости от языка, на котором написана программа, так как массивы в разных языках программирования размещаются в памяти компьютера по-разному. Например, в языке Фортран массивы размещаются по столбцам, а в языках С и Pascal - по строкам [8].

Чтобы проанализировать порядок доступа к данным в процессе использования массивов, необходимо построить дерево обращений к элементам массивов, в узлах которого содержится информация о циклах, а в листьях находятся вхождения массивов в данный цикл (рис. 3). По этому дереву можно определить, к каким элементам массивов происходит обращение, и,

соответственно, подсчитать для них количество заполнений кэш-строк.

Пример

Найдем для 3 двумерных массивов A, B и C наилучший способ размещения их в памяти компьютера при использовании в следующем фрагменте программы:

int const N = 100;

int main()

{

int i,j,k;

int A[N][N], B[N][N], C[N][N];

for (i = 0; i < N; i=i+1)

for (j = 0; j < N; j=j+1)

{

C[j][i] = 1;

for (k = 0; k < N; k=k+1)

A[i][j]= A[i][j] + B[i][k]*C[k][j];

}

Рис. 3. Дерево обращений к элементам массива

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

Сравним полученные данные с реальным временем выполнения программ для всех вариантов размещения данных (рис. 5).

1800000

§ 1600000

и

к 1400000

о

п

Ёр 1200000

сЗ

о 1000000

Ш

н

Р 800000

сз

° 600000

400000 ■ 200000 ■

0

1608584

1622029

394879

428678

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

34250

413549

Исходное

C A и B B и C

Варианты размещения данных

A и C

A, B и C

Рис. 4. Результаты анализа заполнения кэш-линеек; А, В и С - массивы, которые были транспонированы для получения соответствующего способа размещения данных

A

в

70000000 60000000 50000000 3 40000000

н

§ 30000000

ол Рр

m

20000000 10000000 0

Исход ное

B C A и B B и C

Варианты размещения данных

A и C

A,B и C

A

Рис. 5. Время выполнения преобразованных программ

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

Литература

1. Chilimbi T.M., Hill M.D., Larus J.R. Making Pointer-Based

Data Structures Cache Conscious // IEEE Computer. 2000. Vol. 33, № 12. P. 67-74.

2. Волконский В.Ю. Оптимизирующие компиляторы для

архитектуры с явным параллелизмом команд и аппаратной поддержкой двоичной совместимости // Ин-

формационные технологии и вычислительные системы. 2004. № 3. С. 4.

3. Гергель В.П., Стронгин Р.Г. Основы параллельных вы-

числений для многопроцессорных вычислительных систем: учеб. пособие. Н. Новгород, 2003. 184 с.

4. Штейнберг Б.Я. Бесконфликтные размещения массивов

при параллельных вычислениях // Кибернетика и системный анализ. 1999. № 1. С. 166.

5. Касперски К Техника оптимизации программ. Эффек-

тивное использование памяти. СПб., 2003. 464 с.

6. Компиляторы: принципы, технологии и инструментарий

/ А.В. Ахо [и др.]: пер. с англ. М., 2008. 1184 с.

7. Ильин В.А., Позняк Э.Г. Линейная алгебра. М., 1974.

8. Себеста Р.У. Основные концепции языков программи-

рования: пер. с англ. М., 2001. 672 с.

Поступила в редакцию

27 апреля 2009 г

i Надоели баннеры? Вы всегда можете отключить рекламу.