Научная статья на тему 'Организация функционирования распределенных вычислительных систем при обработке наборов масштабируемых задач'

Организация функционирования распределенных вычислительных систем при обработке наборов масштабируемых задач Текст научной статьи по специальности «Математика»

CC BY
304
61
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
РАСПРЕДЕЛЁННЫЕ ВЫЧИСЛИТЕЛЬНЫЕ СИСТЕМЫ / ОПТИМИЗАЦИЯ ФУНКЦИОНИРОВАНИЯ / МАСШТАБИРУЕМЫЕ ЗАДАЧИ / РАСПИСАНИЕ РЕШЕНИЯ ЗАДАЧ / GEOGRAPHICALLY-DISTRIBUTED COMPUTER SYSTEMS / FUNCTIONING OPTIMIZATION / MOLDABLE JOBS

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

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

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

Похожие темы научных работ по математике , автор научной работы — Ефимов Александр Владимирович, Мамойленко Сергей Николаевич, Перышкова Евгения Николаевна

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

Currently, high-performance information processing is based on the using of distributed computing systems (DCS). Amount of elementary machines in such systems can reach up to 106. The monoprogram mode is considered to be quite difficult. The paper considers the multiprogram mode of processing jobs of parallel programs. This mode is used when the amount of programs and their characteristics are known in advance. The characteristics of the programs include the programs rank (the number of parallel branches), the execution time, the penalty for delaying of program execution, etc. Programs can be moldable, i.e. ones may have several options for the parameters which characterize necessary for its execution configuration of the computing resources. Particular attention is paid to the possibility of admissible rankings for program configurations of computing resources and time spent by tasks in the DCS (due to the penalty function for the delay in the solution). The efficiency of a distributed computing system depends on methods of organizing function their resources. The report proposed an approach for moldable jobs of schedule for execution for resource of distributed computing system with genetic optimization method. Schedules are based on distribution jobs for packages, which will be subsequently load on the resources of DCS. Start solutions time of each program is defined as the start solutions time corresponding to the package. Branches of parallel programs consistently distributed over EM. Each package is presented in the form of the gene. Genome is the collection of packages that contain all of the tasks set, each of which selected one of the possible values for the parameters. The initial set of schedules (a population) is constructed using algorithms for packing into containers. The algorithm of gene shuffling is used as the crossover. Mutation is a random selection of one of the parameters of the job. The paper considers the implementation of serial and parallel genetic algorithms.

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

ВЕСТНИК ТОМСКОГО ГОСУДАРСТВЕННОГО УНИВЕРСИТЕТА

2011 Управление, вычислительная техника и информатика № 2(15)

УДК 004.451.42:.44:004.023

А.В. Ефимов, С.Н. Мамойленко, Е.Н. Перышкова ОРГАНИЗАЦИЯ ФУНКЦИОНИРОВАНИЯ РАСПРЕДЕЛЕННЫХ ВЫЧИСЛИТЕЛЬНЫХ СИСТЕМ ПРИ ОБРАБОТКЕ НАБОРОВ МАСШТАБИРУЕМЫХ ЗАДАЧ1

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

Ключевые слова: распределённые вычислительные системы, оптимизация функционирования, масштабируемые задачи, расписание решения задач.

Распределённые вычислительные системы (ВС) относятся к перспективным средствами обработки информации [1]. Основным функциональным элементом распределённой ВС является элементарная машина (ЭМ). Структура ЭМ допускает варьирование от процессорного ядра до конфигураций, включающих многоядерные процессоры и специализированные ускорители (например, вРвРи). Количество ЭМ в распределённых ВС может варьироваться в широких пределах: от десятков до сотен тысяч.

Повышение эффективности эксплуатации ресурсов распределённых ВС связано с использованием технологии параллельного мультипрограммирования [1, 2]. Одной из актуальных проблем организации функционирования ВС в мультипрограммных режимах является планирование решения пользовательских задач. Здесь, по аналогии с [3], под задачей понимается требование пользователя на выполнение параллельной программы. В общем случае проблема планирования решения задач является трудноразрешимой [4]. Перспективной считается разработка приближённых методов и эвристических алгоритмов управления ресурсами ВС.

Повысить эффективность эксплуатации ресурсов ВС и снизить время нахождения задач в очереди возможно, если, в частности, каждая из них будет допускать решение на различных конфигурациях вычислительных ресурсов. В этом случае задачи называют масштабируемыми, или пластичными (шоШаЫе). Исследования пользовательских запросов показывают, что свойством масштабируемости обладают более 80 % задач [5].

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

1 Работа выполнена в рамках интеграционного проекта № 113 СО РАН, при поддержке РФФИ (гранты № 08-07-00022, 10-07-00157, 09-07-90403, 09-07-00095, 08-08-00300), Совета по грантам Президента РФ для поддержки ведущих научных школ (грант НШ-5176.2010.9) и в рамках государственного контракта № 02.740.11.0006 с Минобрнауки РФ.

дачи определяется штраф за задержку её решения. Величина штрафа рассчитывается исходя из характеристик задачи: времени поступления, класса пользователя, и т. п.

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

1. Постановка задачи

Имеются распределённая ВС, состоящая из N элементарных машин, и набор I = {I. | независимых задач, i = 1, L . Каждая задача характеризуется вектором

P ={pk | и величиной штрафа с. за задержку её решения в единицу времени, с. > 0. Элементы вектора pk = (rk, tk, wk) задачи It задают допустимые значения ранга r. и времени решения tt и определяют приоритет wk выбора этих значений, 0 < rk < N, tk > 0, wk > 0 , k = 1, q., q. = \Pt |. «Удовлетворённость» пользователя выбором для решения задачи значений с приоритетом wik оценивается как wk I max wk . Допускается существование в векторе P нескольких элементов с

одинаковым приоритетом. Считается, что в наборе присутствуют задачи с различным количеством q. допустимых значений параметров и возможно взаимодействие ЭМ с любой другой машиной ВС; зависимости величин rk, tk , wk , с. друг от друга отсутствуют.

Необходимо для каждой задачи Ц набора выбрать: kt - номер элемента вектора P, и s. - время начала решения задачи, а также выделить подсистему Jt = {j i EN } элементарных машин ВС, где 0 < k < q{, s. > 0, j - номер ЭМ, EN = {1,2,..., N}, I J. I = rk‘. В результате должен быть сформирован

вектор S = {(ki, s. , Jt)), i = 1, L , называемый расписанием решения задач на ВС.

Характеристиками расписания являются: время T(S) решения всех задач набора и суммарный штраф F (S) за задержку их решения. Кроме этого, качество сформированного расписания оценивается степенью загрузки ресурсов ВС при решении задач.

Требуется найти расписание S* решения задач на вычислительной системе, такое, чтобы

T(S*) = minT(S), T(S) = max{s, + tk‘}; (1)

SiQ i=1, L

F(S*) = miQiF(S), F(S) = jrs,c1, (2)

S i =1

при ограничениях

Vi є {1,2,...,L},\ J \= rjkuVJi є J, Vj2 є J \Ц} ^ j1 Ф j2 ; (3)

Vt > О, П J = 0, X rk < N; (4)

ієН (t) ієН (0

L-1]X-W^> e, ()

і=i max w.

k

где Q - область допустимых расписаний S, H(t) = {і є {1,2,..., N}\ s. < t < s. + tk} -множество номеров задач, решаемых в момент времени t; e - минимально допустимая средняя «удовлетворённость» пользователей. Ограничение (3) определяет, что каждой задаче с учётом выбранных значений параметров должно быть выделено столько ЭМ, сколько требуется для её решения. Ограничение (4) гарантирует, что в каждый момент времени задачи решаются на непересекающихся подсистемах ЭМ и их суммарный ранг не превосходит количества элементарных машин ВС.

Задача (1) - (З) относится к многокритериальной оптимизации [б]. Для решения задачи используем метод приоритетов [б], задавая функции (1) приоритет выше, чем функции (2).

2. Формирование укрупнённых задач

На первом этапе планирования задачи набора разбиваются на подмножества [3] таким образом, чтобы выполнялись ограничения (3) - (З) и достигался минимум функции (1). Подмножества задач будем называть укрупнёнными задачами.

Формально постановка задачи первого этапа приобретает следующий вид. Решением является тройка S1 = (K,M,З), где K = (kt) - вектор выбранных для задач значений k , З = {3m} - множество укрупнённых задач 3m = {I. є I}, m = 1, M, M =\ З \ - количество укрупнённых задач. Требуется определить решение S*, такое, чтобы

M

Ж-

T(S*) = minT(Si), T(Si) = XTm , Tm = maxtk ; (б)

S^Q1 m=1 .єф (m)

при ограничениях

U 3m =З , П 3m = О , X|3ml = L ; ()

M M M

U 3m =3 , П 3m = О , X

m = 1 m =1 m =1

..k.

К ^ N , Ят =Х гі , (8)

ієФ (т)

где Ц - область допустимых решений ^ , Ят - суммарный ранг задач каждого подмножества Зт , Ф(т) = {і є {1,2,..., Ь}\Іі еЗт } - множество номеров задач, помещённых в т-е подмножество. Ограничение (7) требует, чтобы все задачи набора были распределены по укрупнённым задачам. Ограничение (8) задает требо-

вание, чтобы суммарный ранг укрупнённых задач не превосходил количество ЭМ вычислительной системы.

Задача (6) - (8) относится к задачам ортогональной упаковки объектов в контейнеры [7]. При этом задача набора кодируется прямоугольником с шириной, равной гк и высотой ґк . Повороты и пересечения прямоугольников не допускаются. Известно, что эта задача является КР-сложной [8].

2.1. Выбор значений параметров задач набора

При выборе для задач значений к^ необходимо контролировать выполнение

ограничения (5). Представим набор задач I в следующем виде: 10 и I1 и I2, где 10 - подмножество задач набора с одним элементом вектора Рі; Iі - подмножество задач набора, у которых все элементы вектора Рі имеют одинаковый приоритет;

12 - остальные задачи набора; 10 П11 П12 = 0. Тогда ограничение (5) можно

представить в следующем виде:

к,- кі кі

1 х-» wi ^,і ^ Wi,

Ь (І—і-пт + І—і— +І—і—) ^ (9)

гЄф0 тах wk гЄфі тах wk 2 тах wk'

к к к

где Ф0 = {і є {1,2,..., Ь}\Іг є I0}, Ф1 = {і є {1,2,..., Ь}\Іг є I1}

и Ф2 = {і є{1,2,...,Ь}\I є12}.

Очевидно, что для задач из подмножества 10 выбирать значения параметров нет необходимости и первое слагаемое выражения (9) всегда равно \ 10 \. Второе слагаемое выражения (9) также равно \ 11 \ при любом выборе значений параметров для задач из этого подмножества. На выполнение ограничения (5) влияет лишь выбор значений параметров для задач из подмножества 12.

Утверждение 1. Если \ 10\ + \ 11 \> еЬ, то ограничение (5) выполняется при

любом выборе значений параметров для задач подмножества 12. Доказательство очевидно.

Если для набора задач утверждение 1 не справедливо, то используем следующую процедуру выбора значений параметров задач.

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

Шаг 1. Для задач подмножества Iі значения кі выбираются произвольно.

Шаг 2. Вычисляются значения средней «удовлетворённости» пользователей при решении задач набора согласно текущему выбору параметров.

Шаг 3. Произвольно выбирается задача из подмножества 12 и новое значение к для неё.

Шаг 4. Если изменение приоритета значений параметров задачи не приводит к нарушению условия (5), то фиксируется кі и осуществляется переход к шагу 2; в противном случае значение кі для выбранной задачи не меняется.

Шаг 5. Повторяем шаги 2 - 4 до тех пор, пока не будет перебраны все задачи

7-2

подмножества I .

2.2. Генетический алгоритм формирования укрупнённых задач

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

В терминах генетических алгоритмов [9] будем считать:

ген - укрупнённая задача (пакет);

особь или хромосома - допустимое разбиение задач набора при фиксированных значениях кг-;

популяция - несколько особей с различными значениями к ;

функция приспособленности особи - значение функции (6) для соответствующего разбиения задач набора.

Размер популяции задаётся параметром алгоритма и остаётся постоянным в процессе всей эволюции.

2.2.1. Последовательная версия алгоритма

Начальная популяция формируется следующим образом. Первая особь выбирает для каждой задачи к , такое, при котором значения параметров имеют наивысший приоритет wk . Вторая особь - минимум запрашиваемых ресурсов г^ . Третья - максимум «удельной площади» wk: /гк^ . Остальные особи выбирают к случайным образом согласно процедуре, описанной в п.2.1. Далее каждая особь формирует укрупнённые задачи (гены), используя алгоритм БРБИ [10].

На каждом жизненном цикле из популяции выбираются пары особей. Количество пар задается как половина от количества особей в популяции. Для формирования пары из популяции случайным образом выбирается одна особь. Парой для неё выбирается особь, наиболее удалённая от неё по значению функции приспособленности и не состоящая в других парах. Далее над каждой выбранной парой с заданной вероятностью либо выполняется оператор кроссинговера, либо производится мутация родительских особей.

В качестве оператора кроссинговера предлагается алгоритм, в основу которого положен метод перетасовки генов [11]:

Шаг 1. Гены родительских особей помещаются в общий список и сортируются

по степени загрузки ((ЯтТт)-1 Xгеф(т)гЧ ).

Шаг 2. Из полученной последовательности выбираются гены, множества задач в которых не пересекаются. Выбранные гены помещаются в новую особь. Оставшиеся гены расформировываются.

Шаг 3. Для расформированных задач случайным образом выбирается один из параметров. Далее эти задачи распределяются по генам с использованием алгоритма РРБИ (с учетом уже имеющихся генов).

Мутация выполняется над одной или двумя родительскими особями. Оператор мутации с равной вероятностью либо случайным образом изменяет значения параметров задач, гарантируя выполнение ограничения (5), либо выбирает, для заданной доли задач особи, значения параметров, имеющие максимальный приоритет.

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

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

3. Определение последовательности решения укрупнённых задач

На втором этапе определяется последовательность решения укрупнённых задач (пакетов), позволяющая получить минимум функции (2). Состав укрупнённых задач не изменяется.

Пусть Б2 = шх,...,шг,...,шм - некоторая последовательность решения пакетов, где т1 - номер пакета, который будет решаться в 1-ю очередь. Штраф за решение задач при выбранной последовательности решения пакетов определяется как

2.2.2. Параллельная версия алгоритма

м і-1

Р(52) = Х Сті XТтг

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

1=2 г=1 Г

(10)

где Сші = X гєф(ш) С - штраф за задержку решения задач, входящих в ш-й пакет.

Требуется найти такую последовательность Б*, чтобы достичь минимума

функции (10).

Запишем функцию (10) в следующем виде:

^ (Б*) = С * Т - / (Б*),

м

м

где

С = ХСші, Т = ХТш

і =1

і=1

м і

ї (^) = Х Тші X ^ .

і=1 г=1 Г

Очевидно, что минимум (10) достигается при максимуме (11).

Известно утверждение 2 [5, 12]. Для того чтобы последовательность решения пакетов задач обеспечивала минимум функции (10), необходимо и достаточно, чтобы выполнялись неравенства

Т Т Т Т

т1 < т2 < < т1 < < тМ (12)

С ~ С с с '

ту т2 тI тм

4. Формирование итогового расписания решения задач

Итоговое расписание Б * = ((к, ^, Ji)} формируется исходя из Б* и Б* следующим образом. Для к используются значения из Б*. Время начала решения si определяется временем начала решения укрупнённой задачи 5*, в которую она была помещена. Время 5Г определяется найденной последовательностью реше-

* V ч г—1 *

ния укрупнённых задач: ,5Г =^{= Тщ,51 = 0. Итак, Ут е {1,2,...,М},

Vi е Ф(т), 5 = 5*т. Машины ВС распределяются между задачами каждой укрупнённой задачи в соответствии с требованиями.

5. Результаты моделирования работы алгоритма формирования расписаний решения задач

Моделирование и численные эксперименты осуществлялись с использованием ресурсов пространственно-распределённой мультикластерной вычислительной системы Центра параллельных вычислительных технология ГОУ ВПО «Сибирский государственный университет телекоммуникаций и информатики» [13]. Предложенные алгоритмы реализованы с использованием языка программирования С++. Компиляция программ осуществлялась вки вСС с указанием максимально возможной степени оптимизации (-03). Наборы задач генерировались для систем с количеством ЭМ от 21 до 220 на основе модели рабочей загрузки, предложенной в работе [4]. Рассматривались наборы с количеством задач 10, 100, 1000 и 10000. Приоритеты значениям параметров задач задавались путём их простой нумерации.

ГА требует задания трёх параметров: количества жизненных циклов популяций без улучшения потомства (обозначим как 8ТЕР8вА), размера популяции (обозначим как Р8вА), вероятности выполнения кроссинговера и мутации (обозначим как РвА). Кроме этого, алгоритм зависит от минимально-допустимой средней удовлетворённости пользователей (обозначим как е).

Моделирование показало следующее. Для любой минимально допустимой средней «удовлетворённости» пользователей е лучшим значением для 8ТЕР8вА -

5. При дальнейшем увеличении значении 8ТЕР8вА время работы алгоритма растёт, а качество получаемого решения практически не изменяется (рис. 1). ТРРВ(8) -это время решения задач по расписанию, для формирования которого задачам назначены значения параметров с максимальным приоритетом и однократно выполнен алгоритм РРБИ.

С увеличением значения параметра е уменьшается время работы алгоритма. Это связано с тем, что количество вариантов значений параметров с увеличением е сокращается (рис. 2). Наилучшим размером популяции Р8вА является 32 особи

для любого значения минимально допустимой средней «удовлетворённости» пользователей (рис. 3). Вероятность выполнения операторов кроссинговера и мутации существенно не влияет на качество получаемого решения (рис. 4).

Выполнение параллельной версии алгоритма целесообразно для наборов, с количеством задач больше 1000. Ускорение алгоритма практически линейно. Ухудшение значения функции Т(Б) составило не более 10 %.

Моделирование второго этапа подтвердило на практике необходимость и достаточность (12) для обеспечения минимума функции штрафа за задержку решения задач набора (10).

Рис. 1. Влияние параметра 8ТЕР8ОА на качество работы последовательного

ГА (X = 1000, РЭоа = 32, РОА = 0,8, е = 0,95): ■ - улучшение значения функции Т(Б), %; Ш - время работы алгоритма, с

и количество ЭМ вычислительной системы

Рис. 2. Влияние е на время работы последовательного ГА (8ТЕР8ОА=5, РЙоа = 32, РОА = 0,8): *•+*■ - е = 0,5; -*■ - е = 0,7; -А- - е = 0,8; — ><■ - -е = 0,9; —- е = 1

Рис. 3. Влияние размера популяции Р8ОА на качество работы ГА (Ь = 10000, ЗТЕРБод = 5, РОА = 0,8, е = 0,95): - улучшение значения функции Т(Б), %;

■ - время работы алгоритма, с

Рис. 4. Влияние вероятности выполнения операторов кроссинговера и мутации на качество работы ГА (Ь = 10000, Р8ОА = 32, е = 0,95): ■ - улучшение значения функции Г(5), %; ■ - время работы алгоритма, с

Заключение

Разработанные алгоритмы для планирования решения масштабируемых задач на ВС с учётом штрафов за задержку их решения и приоритетов выбора возможных конфигураций подсистем лягут в основу планировщика ресурсов пространственно-распределённой мультикластерной вычислительной системы Центра параллельных в^гчислительных технологий ГОУ ВПО «СибГУТИ».

ЛИТЕРАТУРА

1. Хорошевский В.Г. Архитектура вычислительных систем. М.: МГТУ им. Н.Э. Баумана, 2008. З20 с.

2. Хорошевский В.Г. Модели функционирования большемасштабных распределенных вычислительных систем // Электросвязь. М: Электросвязь, 2004. № 10. С. 30-34.

3. Евреинов Э.В., Хорошевский В.Г. Однородные вычислительные системы. Новосибирск: Наука, 1978. 319 с.

4. Бруно Дж.Л. и др. Теория расписаний и вычислительные машины. М.: Наука, 1984. ЗЗб c.

З. Cirne W. and Berman F. A model for moldable supercomputer jobs // 1ЗШ Intl. Parallel & Distributed Processing Symp. 2001. URL: http://www.lsd.dsc.ufpb.br/papers/moldability-model.pdf (дата обращения: 12.04.2010).

6. ТахаХ. Введение в исследование операций. б-е изд. М.: Вильямс, 2001. 911 с.

7. Коффман Э.Г. Теория расписаний и вычислительные машины. М.: Наука, 1984. ЗЗб с.

8. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые задачи. М.: Мир, 1982. 41б с.

9. Гладков Л.А., Курейчик В.В., Курейчик В.М. Генетические алгоритмы. М.: Физматлит, 200б. 320 с.

10. Coffman E.G. et al. Performance bounds for level-oriented two-dimensional packing algorithms // SIAM Journal on Computing. 1980. V. 9. P. 808-82б.

11. Rohlfshagen P., Bullinaria J.A. A genetic algorithm with exon shuffling crossover for hard bin packing problems // Proc. of the 9th Annual Conf. on Genetic and Evolutionary Computation. ACM NewYork, 2007. P. 1ЗбЗ-1З71.

12. Smith W. Various optimizers for single-stage production. Naval res. Logist. Quart. 3. 19Зб. P. З9-бб.

13. Ресурсы Центра параллельных вычислительных технологий ГОУ ВПО «СибГУТИ». URL: http://cpct.sibsutis.ru (дата обращения: 10.11.2010).

Ефимов Александр Владимирович

Мамойленко Сергей Николаевич

Перышкова Евгения Николаевна

ГОУ ВПО «Сибирский государственный университет

телекоммуникаций и информатики» (г.Новосибирск)

E-mail: [email protected]; [email protected];

[email protected] Поступила в редакцию З декабря 2010 г.

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