Страницы:Кликните, чтобы указать произвольную страницу12далее
Ruins: Организация DDR3 SDRAM на логическом уровне и оптимизация доступа
Ruins
Junior Member
Автор темы
1/1 ответов
7 лет на iXBT, с июля 2017
Инфо Ответить
R
Ruins Junior MemberАвтор темы
8 лет назад / 06 июля 2017 19:35
Hello world,
начал изучать особенности устройства ОЗУ и в какой-то момент понял, что мозги поплыли. Нужная информация как всегда клочками в разных статьях.
На данный момент понял:
  • Тайминги в нс независят от тактов( кроме CAS Write Latency )
  • "Таблица" состоит из строк и столбцов, сначала открываются строки, потом столбцы
  • Читать соседний столбец намного быстрей строки
  • Данные поступают в процессор ещё до закрытия строки
Но остались вопросы:
  • Как связаны логические банки с физическими
  • Как распределять обращения к логическим банкам
  • Где посмотреть размер строки, столбца, банка, желательно программно
  • Как распределять нагрузку между разными модулями памяти
Так же интересно, когда можно начать работу с первым байтом после запроса. То есть ждёт ли процессор всех запрошенных столбцов или можно начать работу с поступающими битами/байтами.
Джамаль
Member
1150/61104 ответов
24 года на iXBT, с июня 2000
Чаще пишет Р Р† "Общий" (21%)
Россия, Самара
Инфо Ответить
Д
Джамаль Member
8 лет назад / 07 июля 2017 15:14
Ruins
Как распределять обращения к логическим банкам
Как распределять нагрузку между разными модулями памяти

Никак. От программиста это спрятано.



Где посмотреть размер строки, столбца, банка, желательно программно

Вот здесь
vertur
Member
4269/4787 ответов, #5 в рейтинге
16 лет на iXBT, с марта 2008
Чаще пишет Р Р† "Программирование" (52%)
Гондурас, default city
Инфо Ответить
v
vertur Member
8 лет назад / 08 июля 2017 04:47
Ruins
Начните с простого. Например, как устроена и по какому протоколу работает К565РУ5.

После этого придет понимание, как минимум того, что процессор не работает напрямую со столбцами / строками.
igotm
Member
1535/1537 ответов
11 лет на iXBT, с ноября 2013
Чаще пишет Р Р† "Программирование" (99%)
Инфо Ответить
i
igotm Member
8 лет назад / 08 июля 2017 10:23
Ruins
а... зачем оно вам?... цель какой?... для чего?...
Ruins
Junior Member
Автор темы
2/2 ответов
7 лет на iXBT, с июля 2017
Инфо Ответить
R
Ruins Junior MemberАвтор темы
8 лет назад / 08 июля 2017 12:36
Да я понял, что этим занимается контроллер памяти. Но ведь можно расположить одно в одном банке, другое в другом и получить параллельное чтение?
Partisan
Member
1701/21047 ответов
25 лет на iXBT, с декабря 1999
Чаще пишет Р Р† "Политика" (54%)
Россия
Инфо Ответить
P
Partisan Member
8 лет назад / 08 июля 2017 12:44
Ruins

Ваши вопросы не имеют никакого отношения к форуму "Программирование".
Ruins
Junior Member
Автор темы
3/3 ответов
7 лет на iXBT, с июля 2017
Инфо Ответить
R
Ruins Junior MemberАвтор темы
8 лет назад / 08 июля 2017 12:50
С каких пор оптимизация кэша и памяти перестало иметь отношение к программированию?
vertur
Member
4270/4788 ответов, #5 в рейтинге
16 лет на iXBT, с марта 2008
Чаще пишет Р Р† "Программирование" (52%)
Гондурас, default city
Инфо Ответить
v
vertur Member
8 лет назад / 08 июля 2017 15:50
Ruins

С каких пор оптимизация кэша и памяти перестало иметь отношение к программированию?
С тех самых пор, когда речь пошла про сигналы CAS, RAS и CS.
igotm
Member
1536/1538 ответов
11 лет на iXBT, с ноября 2013
Чаще пишет Р Р† "Программирование" (99%)
Инфо Ответить
i
igotm Member
8 лет назад / 08 июля 2017 16:38
Ruins

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


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

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

ой... информация, как всегда разрозненна... какой кашмар... о чём вы?... шо вам надо? - это определяет... хде оно разрозненно?...

https://habrahabr.ru/company/intel/blog/282738/
https://habrahabr.ru/post/312078/
https://habrahabr.ru/company/mailru/blog/319194/

Исправлено: igotm, 08.07.2017 17:24

Семёныч
Member
154/432 ответов
23 года на iXBT, с февраля 2002
Чаще пишет Р Р† "Программирование" (29%)
Инфо Ответить
е
Семёныч Member
8 лет назад / 09 июля 2017 06:23
В свое время была занятная книжка - конкретные цифры там, понятно, устарели, но общие принципы всё те же.
igotm
Member
1537/1539 ответов
11 лет на iXBT, с ноября 2013
Чаще пишет Р Р† "Программирование" (99%)
Инфо Ответить
i
igotm Member
8 лет назад / 09 июля 2017 13:52
о... хорошая книжечка, дя... хоть и довольно старенькая уже...

а есть кого-нить в pdf?... в более приличном качестве чем она встречается в дежавю и т.п., то есть - есть ли распознанная?...

название: Касперски Крис - Техника оптимизации программ: Эффективное использование памяти
vertur
Member
4277/4795 ответов, #5 в рейтинге
16 лет на iXBT, с марта 2008
Чаще пишет Р Р† "Программирование" (52%)
Гондурас, default city
Инфо Ответить
v
vertur Member
8 лет назад / 09 июля 2017 17:27
Мыщих начинает входить в классику, LOL.
только узнал что он разбился в феврале, так что уже не LOL. Читать его рассказы про грибы и негритянок было весело.

Исправлено: vertur, 09.07.2017 18:25

igotm
Member
1538/1540 ответов
11 лет на iXBT, с ноября 2013
Чаще пишет Р Р† "Программирование" (99%)
Инфо Ответить
i
igotm Member
8 лет назад / 09 июля 2017 17:51
vertur
эк пусечку на авторитетах укатало... бидняжка...

остаетца надеятца, шо не всё шо она умеет - она подчерпнула где-то у кого-то...

но врушка-вертушка - эпическая...
Джамаль
Member
1151/61108 ответов
24 года на iXBT, с июня 2000
Чаще пишет Р Р† "Общий" (21%)
Россия, Самара
Инфо Ответить
Д
Джамаль Member
8 лет назад / 10 июля 2017 10:23
Ruins
Но ведь можно расположить одно в одном банке, другое в другом и получить параллельное чтение?

Нет, нельзя. Ещё раз скажу вам как электронщик: от программиста это скрыто, вы не сможете принудить систему на базе процессоров x86-64 читать-писать в конкретные микросхемы.

Добавление от 10.07.2017 10:27:

vertur
по какому протоколу работает К565РУ5

Да уж, протокол

Хотя.... ну, в принципе таки да, протокол.

Тогда можно для сравнения рассмотреть ещё и интерфейс микросхемы К573РФ5 (ну или 27С08, чтоб даташит искать удобнее было)
nenin
Member
2992/32378 ответов
22 года на iXBT, с сентября 2002
Чаще пишет Р Р† "Наука" (51%)
Инфо Ответить
nenin Member
8 лет назад / 10 июля 2017 11:33
Семёныч:
В свое время была занятная книжка - конкретные цифры там, понятно, устарели, но общие принципы всё те же.
Это тот кульный хацкер интересный человек , который указал интелю на уязвимость в HT, связанную с тем, что один срид может ковыряться в кеше, выделенном другому сриду?
igotm
Member
1539/1541 ответов
11 лет на iXBT, с ноября 2013
Чаще пишет Р Р† "Программирование" (99%)
Инфо Ответить
i
igotm Member
8 лет назад / 10 июля 2017 22:00
он чото - о чем токо не пишет... разносторонний человек... в части всяких оптимизаций его стиль изложения - заметно цепляет... этакий... весьма обстоятельный исследователь...

Исправлено: igotm, 10.07.2017 22:40

KPAH
Expert
3035/18658 ответов
23 года на iXBT, с декабря 2001
232 фото на iXBT.photo
Чаще пишет Р Р† "Общий" (37%)
Россия, Москва
Инфо Ответить
KPAH Expert
8 лет назад / 11 июля 2017 20:47
vertur
С тех самых пор, когда речь пошла про сигналы CAS, RAS и CS.
Программирование оно разное бывает. Некоторые на Verilog программируют контроллеры DRAM.
rGlory
Expert
5931/6021 ответов
23 года на iXBT, с марта 2001
50 фото на iXBT.photo
Чаще пишет Р Р† "Программирование" (97%)
США, Philadelphia, PA
Инфо Ответить
rGlory Expert
8 лет назад / 11 июля 2017 23:39
KPAH
Ну судя по тому, что ТС упомянул процессор, он не с FPGA работает. Да и работал бы, таких вопросов не задавал.
AzikAtom
Member
1113/17522 ответов
19 лет на iXBT, с марта 2005
242 фото на iXBT.photo
Чаще пишет Р Р† "Авто" (32%)
Россия, Адыгея, Майкоп
Web-страница
Инфо Ответить
A
AzikAtom Member
8 лет назад / 12 июля 2017 17:45
Ruins
Как распределять нагрузку между разными модулями памяти
Очень просто - располагать данные в памяти по последовательным адресам. Как вы уже узнали, сначала выбирается строка, что занимает много времени, затем из неё выбирается несколько "столбцов" подряд. Плюс ещё кэш линии процессора, вроде, были по 32 байт. Соответственно, контроллер считывает 32 байт и процессор работает с ними, пока считываются следующие 32 байт. То есть, если вы будете читать память с шагом хотя бы в 32 байт, то скорость упадёт катастрофически. Надо последовательно.
С записью примерно так же дела обстоят, кроме того, что при изменении 1 байта контроллер считывает данные из памяти, заполняет кэш линию (32 байта), меняет 1 байт и отправляет их обратно. Т.е., и при записи желательно писать подряд. А если использовать SSE команду movntq, то часто процессор сможет обойтись без предварительного чтения кэш линии, а сразу будет писать в память.
vertur
Member
4278/4796 ответов, #5 в рейтинге
16 лет на iXBT, с марта 2008
Чаще пишет Р Р† "Программирование" (52%)
Гондурас, default city
Инфо Ответить
v
vertur Member
8 лет назад / 17 июля 2017 00:36
AzikAtom

А если использовать SSE команду movntq
А кто сказал что речь идет о x86 ?

Добавление от 17.07.2017 00:41:

AzikAtom

Очень просто - располагать данные в памяти по последовательным адресам
В то же время для достижения максимальной производительности данные должны быть выровнены. И это основной фактор влиящий на производительность.
PRODIGY
Junior Member
1/1 ответов
7 лет на iXBT, с августа 2017
Инфо Ответить
P
PRODIGY Junior Member
7 лет назад / 24 августа 2017 19:24
igotm
а есть кого-нить в pdf?... в более приличном качестве чем она встречается в дежавю и т.п., то есть - есть ли распознанная?...

название: Касперски Крис - Техника оптимизации программ: Эффективное использование памяти
У меня есть в формате DOC, + исходники. (11Мб)
Полная коллекция статей Криса лежит здесь (pdf\doc): https://www.evilfingers.com/publications/research_RU.php

А по теме - много инфы по ядру SDRAM можно почерпнуть из даташитов на чипы памяти.
IlyaK
Member
9/628 ответов
12 лет на iXBT, с июля 2012
Чаще пишет Р Р† "Рынок труда" (42%)
Инфо Ответить
I
IlyaK Member
7 лет назад / 03 сентября 2017 19:58
Ruins
Как связаны логические банки с физическими
Логический банк состоит из нескольких физических.

Допустим, у Вас есть N микросхем, объединенных в один ранк. В каждой по M банков.
Логический банк 1 состоит из первых банков всех микросхем. Всего у Вас M логических банков.

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

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

Учтите что в современных машинах контроллер памяти находится в CPU, тогда как во времена книги (2003 г) он был в чипсете (memory hub, или в north bridge в старых моделях)

Где посмотреть размер строки, столбца, банка, желательно программно
Эта информация есть в SPD -- маленькой ROM на памяти. Она подключена по шине I2C, и её считывает BIOS/UEFI и на основе ее (и настроек пользователя) программирует контроллер памяти.

Firmware предоставляет эту информацию через SMBIOS (DMI)(https://www.dmtf.org/sites/default/files/standards/d…DSP0134_3.1.1.pdf) спец. таблицы в памяти с описанием платформы (для людей).

Операционки имеют API для этого. В винде можно поглядеть в WMI классы Win32_PhysicalMemory .Win32_MemoryDevice и Win32_SMBIOSMemory. Можно так же глянуть как это делает CPU-Z.

На линуксе есть dmidecode (dmi -- старое название smbios).

Можно напрямую прочитать SPD через I2C (в линукс должен уметь i2c-tools, кроме того все устройства I2C видны через ACPI, следовательно должны быть методы (I2C Read в винде, например, но нужен драйвер))

Как распределять нагрузку между разными модулями памяти
Опять таки: это делает контроллер если Вы читаете последовательно.

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

Процессор (точнее та его часть, что расположена до контроллера памяти) знать не знает про столбцы. Для него пространство линейно.


Столбцы вываливаются на sense ampl, оттуда попадают на дорожки, оттуда в кеш и только оттуда в CPU.
Если Вы сделали MOV EAX, [FOO], то можете быть уверены что к моменту следующего обращения к EAX у Вас там будет значение по адресу FOO (разумеется, с учетом превращения виртуального адреса в физический).

Это гарантия набора инструкций x86.

Не знаю как в других платформах, но в x86 процесс преобразования линейной памяти в геометрию DRAM полностью прозрачен для программиста.

Если умеете английский то вот тут с 36 минуты оч хорошо объясняют (https://www.youtube.com/watch?v=AXf_C5qOm8o&inde…I7b3JCL1TWybTDtKq)

Вот тут хорошие слайды: http://www.ece.umd.edu/class/enee759h.S2003/lectures/Lecture2.pdf

А про книжку Криса Вам уже рассказали.
PRODIGY
Junior Member
6/6 ответов
7 лет на iXBT, с августа 2017
Инфо Ответить
P
PRODIGY Junior Member
7 лет назад / 05 сентября 2017 19:52
Ruins
Как связаны логические банки с физическими
..подкину и я свои 5-шекелей в копилку темы:


HWiNFO32 Version 5.50-3130
--------------------------
Memory:
Module Type SO-DIMM / DDR3-SDRAM
Module Size 2048 МB
Memory Speed 800.0 MHz (DDR3-1600 / PC3-12800)
Burst Lengths(BL) 8

SPD:
Row Address Bits 15
Column Address Bits 10
Number Of Banks 8
Number Of Ranks 1
Device Width 8 bits
Bus Width 64 bits
Module Voltage 1.5 V

SPD показывает организацию модуля памяти..
8 логических банков требуют 3-бита для адресации, которые (на самом деле) являются старшими битами адреса-строки (RowAddr). Итого получаем 18-бит, которыми можно адресовать всего 262.144 строк матрицы. Если разделить 262144 на 8, то младшие 15-бит адреса будут одинаковы для всех банков, поэтому разводим их параллельно по всем\восьми чипам модуля памяти.

Три старших бита BA[2:0] (Bank Activate) контроллёр памяти отсекает от 18-битного адреса строки, и направляет их на дешифратор банка, который собран по схеме "3-in-8". Это позволяет автоматом выбирать номер банка, по адресу строки:
       |<-- MA[14:0] -->|       Диапазон строк
       |                |
   000.111.1111.1111.1111  <--  000000..032767   Банк(0)
   001.111.1111.1111.1111  <--  032768..065535   Банк(1)
   010.111.1111.1111.1111  <--  065536..098303   Банк(2)
   011.111.1111.1111.1111  <--  098304..131071   Банк(3) <---
   100.111.1111.1111.1111  <--  131072..163839   Банк(4)
   101.111.1111.1111.1111  <--  163840..196607   Банк(5)
   110.111.1111.1111.1111  <--  196608..229375   Банк(6)
   111.111.1111.1111.1111  <--  229376..262144   Банк(7)
   | |            ___
   +-+-----/-3-->| Д |
   BA[2:0]       |   |--/-8---> Активация банка
                 |___|
 
   Лин\строка :  100100d = (011).000.0111.0000.0100b
   DRAM-строка:  банк(3), строка(1796)
 
Организация чипа (х8) подразумевает соединение между собой каждого из восьми столбцов матрицы, что приводит к слиянию их адресов (ячейка 8-бит). Организация закладывается на этапе производства чипа разработчиком:
  Организация (х1)              Организация (х8)
                         _____________    _____________
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_
 _|_|_|_|_|_|_|_|_     _|_|_|_|_|_|_|_|__|_|_|_|_|_|_|_|_  
  | | | | | | | |       | | | | | | | |  | | | | | | | |  
  | | | | | | | |       |                |
  0 1 2 3 4 5 6 7       0                1     <---- номер столбца
Для адреса столбцов выделяется 10-бит МА[9:0], значит всего 1-байтных столбцов в матрице =1024. Их адрес приходит по тем-же линиям МА[14:0], что и адрес строки. То есть уже разведён по чипам параллельно. По стробу RAS#, мультиплексор адреса в чипе переключает линии адреса МА[14:0] на дешифратор строки, ..по стробу CAS# - на декодер столбца.

Несложной арифметикой можно получить размер модуля (в данном случае 2Gb)..
Если одна строка чипа равна 1Кб (1024 однобайтных столбца), а всего строк в матрице 262144, то ёмкость одного чипа будет 256 Мбайт. 8 чипов дадут на выходе 2 гига.

Таким образом, при организации физического банка (ранка), все управляющие-линии и линии-адреса разводятся по 8-ми чипам параллельно, а 8-битные инфо-шины каждого из чипов - соединяются последовательно, образуя 64-битную\внешнюю шину модуля к процессору.

В ранке, кол-во строк и банков остаётся прежним - 8 банков, по 32768-строки в каждом. А вот общее кол-во столбцов увеличится до 1024*8(чипов)=8192, хотя адресуемых по-прежнему только 1024. Так-как адреса столбцов совпадают для всех чипов (параллельная разводка), то при выборе столбца автоматом выбираются и соответствующие столбцы в соседних чипах. Общая для всех чипов строка представляет из-себя "страницу DRAM-памяти" (здесь 8Кб).

Модули DDR заточены для пакетной передачи данных (чтение соседних ячеек без подачи адреса столбца). Длинна пакета задаётся параметром "Burst Length" (BL=1,2,4,8,16,Page). Основное назначение пакетной передачи - заполнение данными линейки кэша за одно обращение к памяти. Размер кэш-строки совремнных ЦП равен 64-байта, а параметр(BL) у меня равен(8). Подсмотреть текущее значение(BL) можно в "Аиде" (в разделе чипсет), или прочитать из поля(10h) данных SPD (отчёт CPU-Z).

После открытия DRAM-страницы стробом(RAS#) и заполнения буфера "Sense Amplifier" данными активной страницы, подаётся адрес столбца, который выбирает смещение нужного байта в SenseAMP. Страница остаётся открытой на всё время пакетного цикла (низкий уровень RAS#), и контроллёр продолжает читать смежные (от указанного столбца) ячейки памяти по внутреннему счётчику чипа, исходя из значения BL=8.

По окончанию пакетного цикла, DRAM-страница закрывается (высокий уровень RAS#), и в выходном буфере модуля оказываются 64-байта данных, которые отправляются на внешнюю шину модуля и далее в кэш. DRAM-cтраница возвращается из SenseAMP обратно на свою строку, адрес которой всё-это время был защёлкнут в регистре-защёлке адреса строки - регенерация страницы памяти.
OXPEHOMETP
Member
1084/1110 ответов
22 года на iXBT, с февраля 2003
Чаще пишет Р Р† "Программирование" (97%)
Инфо Ответить
O
OXPEHOMETP Member
7 лет назад / 11 сентября 2017 11:16
Про отношение подобных тем к программированию - шутки шутками, а это вещь весьма серьёзная (скоро и мне предстоит в этом ещё раз убедиться).

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

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

Нет значка Нет значка Р’РѕС‚ тут! Лампочка Восклицание Р’РѕРїСЂРѕСЃ Класс! Улыбка Злость Огорчение РџРѕРіРѕРІРѕСЂРёРј? Краснею Подмигивание Ругаю РћРґРѕР±СЂСЏСЋBIUdelSxsupxsuboffsp spoilerqurlimgvideo• list1. list1 codeprecenter-hr-rusQWE→ЙЦУ
файлыочистить
Ваше имя: Авторизуйтесь Предпросмотр В полную форму
вставить выделенную цитату в окно ответа
Если Вы считаете это сообщение ценным для дискуссии (не обязательно с ним соглашаться), Вы можете поблагодарить его автора, а также перечислить ему на счет некоторую сумму со своего баланса (при отзыве благодарности перечисленная сумма не будет вам возвращена).
Также вы можете оценить сообщение как неудачное.
В течение суток можно 20 раз оценить сообщения разных участников (купите Premium-аккаунт, либо оплачивайте оценки сверх лимита).
Если Вы считаете это сообщение ценным для дискуссии (не обязательно с ним соглашаться), Вы можете поблагодарить его автора, а также перечислить ему на счет некоторую сумму со своего баланса (при отзыве благодарности перечисленная сумма не будет вам возвращена).
Также вы можете оценить сообщение как неудачное.
В течение суток можно 20 раз оценить сообщения разных участников (купите Premium-аккаунт, либо оплачивайте оценки сверх лимита).
Страницы:Кликните, чтобы указать произвольную страницу12далее