Cheb's Game Engine

Планы, идеология, архитектура и т.п.

Модератор: Модераторы

Re: Cheb's Game Engine

Сообщение runewalsh » 03.02.2018 02:45:47

>над XMM регистрами побитовые операции невозможны, а напрямую в регистр общего назначения тоже невозможно передать
Точно? Я в ассемблере мало что понимаю, но гугл говорит ровно обратное: что есть варианты MOV[D|etc.] для xmm → регистр общего назначения, равно как и сдвиги и побитовые операции для xmm.
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 332
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Cheb » 03.02.2018 03:42:41

что есть варианты MOV[D|etc.] для xmm → регистр общего назначения, равно как и сдвиги и побитовые операции для xmm.

:shock:
Буду разбираться!

..малина ещё не закончила..
Код: Выделить всё
Raspberry Pi 3 + PC2-6400 (RAM limit 0.8 GFLOPS):
    ..checking rsqrt() -- на этой платформе это копия bd_rsqrt()
      ..ok, in 1433 (pure 271) seconds (0.00787 GFLOPS)
      ..md5 checksum = 5D3136ECCF66CB8F5D278CD651B1DB07
    ..checking bd_rsqrt()
      ..ok, in 1432 (pure 270) seconds (0.00789 GFLOPS)
      ..md5 checksum = 5D3136ECCF66CB8F5D278CD651B1DB07
    ..checking sqrt()
      ..ok, in 1208 (pure 56.3) seconds (0.0378 GFLOPS)
      ..md5 checksum = 5A50783537304E8D28DDC3C7D7FC3E6A
    ..checking multiplication by Pi..
      ..ok, in 1290 (pure 78.7) seconds (0.0533 GFLOPS)
      ..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
    ..checking bd_sin()..
      ..ok, in 379 (pure 78.4) seconds (0.0136 GFLOPS)
      ..md5 checksum = 9E39629C4577EEF4BDE30EE13047F9F9
    ..checking sin()..

Но уже сейчас видно нечто шокирующее!
Обычный квадратный корень -
а) детерминистичный
б) быстрее "быстрого обратного" по методу Кармака - на писи в два раза, а на малине - аж в пять.
Завтра повторю, добавив в тест вариант 1/sqrt() (а эта байда служит для нормализации векторов).
Понятно, что быстрый инверсный из SSE2 на писях немного быстрее (а когда AVX запрягу - вообще зверь, интеловские процы нормализуют чуть не до одного вектора за такт). Но те - не детерминистичные, в физике не используешь.

Добавлено спустя 8 часов 57 минут 27 секунд:
Код: Выделить всё
    ..checking sin()..
      ..ok, in 602 (pure 298) seconds (0.00359 GFLOPS)
      ..md5 checksum = 4DE8EFC27CBB692E5E3DEB7A7E561EAB

Ииии, чётко видно, что синус в пятнадцать раз медленней умножения *на всех платформах*
Зато детерминистичный. :lol:

Сейчас модифицирую тесты, померю насколько честный 1/sqrt() окажется быстрее быстрого обратного квадратного корня по методу Кармака :shock:

Добавлено спустя 50 минут 1 секунду:
Рукалицо :shock:

На замшелом AMD честный 1/sqrt(x) одинаков по скорости с кармаковским хаком.
На интеле - на 20% медленнее.

Зато на Raspberry Pi 3 - в два с половиной раза быстрее. В два с половиной! :shock:

У малины, похоже, просто перекачан fpu мускул... :lol:

Добавлено спустя 4 часа 24 минуты 8 секунд:
Финальный результат:
Код: Выделить всё
win32 + sse2 @ i5-2450M 2.5GHz + PC3-10600 (RAM limit 1.3 GFLOPS):
(intel burn test gives ~20 GFLOPS for a single core)
  Checking CPU/compiler combo for floating point determinism...
    ..checking 1/sqrt()
      ..ok, in 67 (pure 21.7) seconds (0.0981 GFLOPS)
      ..md5 checksum = 923C6EB0CDC9F67EB190EB5DEE8E3B14
    ..checking sqrt()
      ..ok, in 56 (pure 10.8) seconds (0.197 GFLOPS)
      ..md5 checksum = 5A50783537304E8D28DDC3C7D7FC3E6A
    ..checking rsqrt()
      ..ok, in 52 (pure 7.11) seconds (0.3 GFLOPS)
      ..md5 checksum = 95389BA76240737D6323FA5F7A549852
    ..checking division..
      ..ok, in 72 (pure 21.3) seconds (0.197 GFLOPS)
      ..md5 checksum = 2D84289D63C27EC1F701E7B20960A3A1
    ..checking multiplication by Pi..
      ..ok, in 58 (pure 7.03) seconds (0.597 GFLOPS)
      ..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
    ..checking bd_rsqrt()
      ..ok, in 63 (pure 18.4) seconds (0.116 GFLOPS)
      ..md5 checksum = 985241AB7340A4550C995119AEEC5E7B
    ..checking bd_sin()..
      ..ok, in 18 (pure 5.62) seconds (0.19 GFLOPS)
      ..md5 checksum = 9E39629C4577EEF4BDE30EE13047F9F9
    ..checking sin()..
      ..ok, in 40 (pure 27.3) seconds (0.0393 GFLOPS)
      ..md5 checksum = 4DE8EFC27CBB692E5E3DEB7A7E561EAB


    
win32 + sse2 @ Phenom II X6 1090T 3.2GHz + PC3-8500 (RAM limit 1.0 GFLOPS):
(intel burn test gives ~10 GFLOPS for a single core)
    ..checking 1/sqrt()
      ..ok, in 56 (pure 17.8) seconds (0.12 GFLOPS)
      ..md5 checksum = 923C6EB0CDC9F67EB190EB5DEE8E3B14
    ..checking sqrt()
      ..ok, in 48 (pure 9.91) seconds (0.215 GFLOPS)
      ..md5 checksum = 5A50783537304E8D28DDC3C7D7FC3E6A
    ..checking rsqrt()
      ..ok, in 49 (pure 10.8) seconds (0.198 GFLOPS)
      ..md5 checksum = 099065E6029AB6F582165CC92DECF8AC
    ..checking division..
      ..ok, in 63 (pure 16) seconds (0.262 GFLOPS)
      ..md5 checksum = 2D84289D63C27EC1F701E7B20960A3A1
    ..checking multiplication by Pi..
      ..ok, in 59 (pure 10.8) seconds (0.387 GFLOPS)
      ..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
    ..checking bd_rsqrt()
      ..ok, in 57 (pure 18.4) seconds (0.116 GFLOPS)
      ..md5 checksum = 985241AB7340A4550C995119AEEC5E7B
    ..checking bd_sin()..
      ..ok, in 20 (pure 7.95) seconds (0.135 GFLOPS)
      ..md5 checksum = 9E39629C4577EEF4BDE30EE13047F9F9
    ..checking sin()..
      ..ok, in 43 (pure 31.8) seconds (0.0337 GFLOPS)
      ..md5 checksum = 4DE8EFC27CBB692E5E3DEB7A7E561EAB


    
Raspberry Pi 3 + PC2-6400 (RAM limit 0.8 GFLOPS):
    ..checking rsqrt()
      ..ok, in 1433 (pure 271) seconds (0.00787 GFLOPS)
      ..md5 checksum = 5D3136ECCF66CB8F5D278CD651B1DB07
    ..checking bd_rsqrt()
      ..ok, in 1432 (pure 270) seconds (0.00789 GFLOPS)
      ..md5 checksum = 5D3136ECCF66CB8F5D278CD651B1DB07
    ..checking sqrt()
      ..ok, in 1208 (pure 56.3) seconds (0.0378 GFLOPS)
      ..md5 checksum = 5A50783537304E8D28DDC3C7D7FC3E6A
    ..checking multiplication by Pi..
      ..ok, in 1290 (pure 78.7) seconds (0.0533 GFLOPS)
      ..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
    ..checking bd_sin()..
      ..ok, in 379 (pure 78.4) seconds (0.0136 GFLOPS)
      ..md5 checksum = 9E39629C4577EEF4BDE30EE13047F9F9
    ..checking sin()..
      ..ok, in 602 (pure 298) seconds (0.00359 GFLOPS)
      ..md5 checksum = 4DE8EFC27CBB692E5E3DEB7A7E561EAB


- и оставляю пока это.

Выводы - воодушевляющие.

1. Я могу спокойно использовать чистые вычисления с плавающей запятой и не париться.
2. Оптимизировать можно потом, уже после того, как будет работающий мультиплеер: всякие функции пакетного просчёта физики и нормализации векторов, на SSE, AVX или что там ещё взбредёт.

По крайней мере, камень с плеч - большой и толстый :lol:

Добавлено спустя 1 минуту 31 секунду:
равно как и сдвиги и побитовые операции для xmm.

Сдвиги, самка собаки, побайтовые :evil: А нужен shr 1.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 619
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение скалогрыз » 04.02.2018 02:00:31

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

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

в итоге никаких лишних if-ов, jit-ов - только динамическая перекомпоновка кода.
скалогрыз
долгожитель
 
Сообщения: 1651
Зарегистрирован: 03.09.2008 02:36:48

Re: Cheb's Game Engine

Сообщение Mirage » 04.02.2018 04:46:35

Судя по всему, планируется мультиплейер с фиксированными тиками, когда на всех машинах симулируется все одинаково. Иначе зачем детерминизм?
Если так, то рекомендую по-быстрому сделать прототип, чтобы убедиться, что сие не работает. И не тратить много времени.
А с корнями странно, да. Вроде я мерял и метод Кармака (вручную на асме) был куда быстрее. Надо перемерять.
Mirage
энтузиаст
 
Сообщения: 763
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Cheb's Game Engine

Сообщение Cheb » 04.02.2018 16:00:49

Если так, то рекомендую по-быстрому сделать прототип, чтобы убедиться, что сие не работает. И не тратить много времени.

Как я уже писал ранее, планируется продвинутый вариант этой системы, с локстепом в прошлом (0.3..0.5 секунд) поверх которого - нашлёпка лагокомпенсации. Сама идея оформилась где-то в 2008-м, кажется, и с тех пор ничего принципиально нового я не придумал.

и метод Кармака (вручную на асме) был куда быстрее.

Через классический FPU или через SSE?
Оно именно из-за последнего не работает, из-за отсутствия такой штуки, как сдвиг на один бит вправо.

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

Примерно так.
Причём, будет всё устроено очень тупо: 95% кода, что занимают 5% времени, будут статическими, безо всяких изысков. А 5% кода, что занимают 95% времени - будут иметь как базовые варианты (по 1 штуке) так и пакетные (например, нормализация 4 векторов на SSE2 или нормализация 8 векторов за раз на AVX) и процедура "а нормализуй-ка мне N векторов" будет во время выполнения, на if'ах и case'ах, вызывать их в нужной комбинации при проходе по массиву: например, что делится на 8 - на AVX, остаток - по одной штуке на обычной математике.

Добавлено спустя 18 минут 34 секунды:
Провёл новую серию тестов. Встал вопрос: а зачем?
На писях, реализованное на SSE, тупое в лоб решение 1/sqrt() обгоняет метод Кармака просто за счёт брутфорса - т.к. делает 4 операции одновременно. И оно детерминистично!
(а когда AVX запрягу - вообще все лягут)
На малине, тупое в лоб решение 1/sqrt() обгоняет метод Кармака как бог черепаху просто потому что у малины перекачаный FPU. И оно детерминистично!

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

Код: Выделить всё
CPU Phenom II X6 1090T
  TSC frequency: 3.16 GHz
  Checking CPU/compiler combo for floating point determinism...
    ..checking 1/sqrt using SSE packed 4-SIMD asm
      ..ok, in 43 (pure 5.19) seconds (0.411 GFLOPS)
      ..md5 checksum = 923C6EB0CDC9F67EB190EB5DEE8E3B14
    ..checking 1/sqrt()
      ..ok, in 55 (pure 17.9) seconds (0.119 GFLOPS)
      ..md5 checksum = 923C6EB0CDC9F67EB190EB5DEE8E3B14
    ..checking sqrt()
      ..ok, in 47 (pure 9.94) seconds (0.214 GFLOPS)
      ..md5 checksum = 5A50783537304E8D28DDC3C7D7FC3E6A
    ..checking SSE RSQRTPS packed 4-SIMD
      ..ok, in 40 (pure 2.21) seconds (0.966 GFLOPS)
      ..md5 checksum = 099065E6029AB6F582165CC92DECF8AC
    ..checking rsqrt()
      ..ok, in 50 (pure 10.9) seconds (0.196 GFLOPS)
      ..md5 checksum = 099065E6029AB6F582165CC92DECF8AC
    ..checking division..
      ..ok, in 63 (pure 16.1) seconds (0.261 GFLOPS)
      ..md5 checksum = 2D84289D63C27EC1F701E7B20960A3A1
    ..checking multiplication by Pi..
      ..ok, in 58 (pure 10.8) seconds (0.389 GFLOPS)
      ..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
    ..checking bd_rsqrt()
      ..ok, in 58 (pure 19.2) seconds (0.111 GFLOPS)
      ..md5 checksum = 985241AB7340A4550C995119AEEC5E7B
    ..checking bd_sin()..
      ..ok, in 20 (pure 8.07) seconds (0.133 GFLOPS)
      ..md5 checksum = 9E39629C4577EEF4BDE30EE13047F9F9
    
CPU Core i5-2450M 2.50GHz
  TSC frequency: 2.44 GHz)
  Checking CPU/compiler combo for floating point determinism...
    ..checking 1/sqrt using SSE packed 4-SIMD asm
      ..ok, in 50 (pure 5.27) seconds (0.404 GFLOPS)
      ..md5 checksum = 923C6EB0CDC9F67EB190EB5DEE8E3B14
    ..checking 1/sqrt()
      ..ok, in 65 (pure 20.8) seconds (0.102 GFLOPS)
      ..md5 checksum = 923C6EB0CDC9F67EB190EB5DEE8E3B14
    ..checking sqrt()
      ..ok, in 56 (pure 10.6) seconds (0.201 GFLOPS)
      ..md5 checksum = 5A50783537304E8D28DDC3C7D7FC3E6A
    ..checking SSE RSQRTPS packed 4-SIMD
      ..ok, in 48 (pure 2.14) seconds (0.996 GFLOPS)
      ..md5 checksum = 95389BA76240737D6323FA5F7A549852
    ..checking rsqrt()
      ..ok, in 52 (pure 6.97) seconds (0.306 GFLOPS)
      ..md5 checksum = 95389BA76240737D6323FA5F7A549852
    ..checking division..
      ..ok, in 72 (pure 20.8) seconds (0.201 GFLOPS)
      ..md5 checksum = 2D84289D63C27EC1F701E7B20960A3A1
    ..checking multiplication by Pi..
      ..ok, in 58 (pure 6.85) seconds (0.613 GFLOPS)
      ..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
    ..checking bd_rsqrt()
      ..ok, in 66 (pure 20) seconds (0.106 GFLOPS)
      ..md5 checksum = 985241AB7340A4550C995119AEEC5E7B
    ..checking bd_sin()..
      ..ok, in 19 (pure 5.59) seconds (0.191 GFLOPS)
      ..md5 checksum = 9E39629C4577EEF4BDE30EE13047F9F9


Ну, и?... Нету методу Кармака места в современном программировании.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 619
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Mirage » 05.02.2018 01:04:54

Cheb писал(а):Как я уже писал ранее, планируется продвинутый вариант этой системы, с локстепом в прошлом (0.3..0.5 секунд) поверх которого - нашлёпка лагокомпенсации. Сама идея оформилась где-то в 2008-м, кажется, и с тех пор ничего принципиально нового я не придумал.


Просто когда я делал сетевую игру для эйрхоккея (2004), то мне говорили умные люди, и я тоже не поверил. А зря.
Гимора много так делать, а работает приемлемо только в LAN с пингом < 1ms.
Потому как каждый тик сервер должен принять и отправить обратно.

Cheb писал(а):Через классический FPU или через SSE?


Да на pure pascal. Кстати на асме через FPU настолько не быстрее, что смысла нет.
И это точно быстрее, чем fsqrt.
А на SSE наверное уже быстрый sqrt.
Mirage
энтузиаст
 
Сообщения: 763
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Cheb's Game Engine

Сообщение Cheb » 05.02.2018 07:53:08

Гимора много так делать, а работает приемлемо только в LAN с пингом < 1ms.

Естессно, если *чистый* lockstep то оно годится только для 2-3 игроков по локалке с FPS 20.
Подробнее - лень воздух сотрясать, ищи вдоль темы взад.

А на SSE наверное уже быстрый sqrt.

Ну, не магически быстрый, но достаточно, чтобы 1/sqrt() на sse asm почти не отставал от простого умножения на чистом паскале.
Но это детерминистичный.
Там есть спецкоманды 1/x и 1/sqrt(x), выполняющиеся за пару тактов - при правильном написании кода на пару миллиардов операций в секунду точно выйдешь.
См. выше результат для "..checking SSE RSQRTPS packed 4-SIMD".
Как я уже упоминал, у интела есть пример, как на AVX нормализовать по вектору за такт с хвостиком. Это где-то два миллиарда векторов вв секунду выйдет на среднем процессоре (и это только один поток!).
Но я такие чудеса могу только разве что для анимации на CPU применить, т.к. они не детерминистичные и для моей физики не годятся:

интел
..checking SSE RSQRTPS packed 4-SIMD
..ok, in 48 (pure 2.14) seconds (0.996 GFLOPS)
..md5 checksum = 95389BA76240737D6323FA5F7A549852

амд
..checking SSE RSQRTPS packed 4-SIMD
..ok, in 40 (pure 2.21) seconds (0.966 GFLOPS)
..md5 checksum = 099065E6029AB6F582165CC92DECF8AC

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

Добавлено спустя 7 часов 20 минут 3 секунды:
P.S. Кстаааати, оно у меня неоптимально работает: сначала заполняя 32 Мб массив, потом вторым проходом выполняя вычисления. И 0.9 гигафлопса подозрительно похоже на пропускную способность памяти (8Гб/с) - т.к. размер числа 4 байта, и делим на два поскольку идут и чтение и запись.

Я так сделал поскольку на малине доступный таймер не очень высокого разрешения (1МГц).
Надо переделывать.
[тяжкий стон] :x

Добавлено спустя 1 час 47 секунд:
Оооо-кей.
Частично переделал под размер чанка 16 Кб, чтобы с запасом уклалось в L1 кэш.
Во превых, обычное умножение побежало в полтора раза шустрее.
Во вторых...
Checking CPU/compiler combo for floating point determinism...
..checking x * Pi (typed const)..
..ok, in 56 (pure 4.29) seconds (0.978 GFLOPS)
..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
..checking x * 3.141592653589793 (inline const)..
..ok, in 57 (pure 5.39) seconds (0.778 GFLOPS)
..md5 checksum = 0FC3738303DEA3CFC8C6F7AFBF585BE6 - SURPRISE BUTTSECKS
..checking x * float(3.141592653589793) (inline const with type-cast)..
..ok, in 56 (pure 4.25) seconds (0.986 GFLOPS)
..md5 checksum = 9CA6E7B818FA046C3DAE722C35196729
.. без тайпкаста он в даблах считал, курва :evil:
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 619
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Cheb » 07.02.2018 15:57:06

Поучаствовал в интересном обсуждении на gamedev.ru. Появились идеи, *как* запрячь дополнительные ядра, не делая основную логику распараллеливаемой.
Ок, кпд будет заметно < 100%, но это, в принципе, пофиг.

1. Тщательно расслаиваем логику и физику на реально сложные взаимодействия, на классах, занимающие 10% времени - и тупые вычисления, работающие с record'ами по ссылкам, занимающие 90% времени и разделяемые на потоковые задачи.
2. Потоковые задачи разделяются от логики по времени - т.е. перед их запуском логика останавливается (и делается только для чтения, если осилю спец. дичпетчер памяти) и запрещаются счётчики ссылок в _AddRef/_Release.
3. Потоковые задачи оформляют свои результаты в виде спец.классов в пуле результатов. Никакой взаимосвязи не допускается, модификация основной логики не допускается.
4. Потоковые задачи стираются без следа.
5. Реактивируется логика, разблокируются счётчики ссылок, работаем с результатами.

Как пример, движение партиклов
1. Основная логика - поток №1
2. Обход чанков, расчёт изменений в освещении, уровнях текущей воды и прочая - распараллелено.
3. Сведение результатов, модификация чанков согласно полученным дельтам - поток №1.
4. Обход партиклов, проверка столкновений и суммирование сил - распараллелено
5. Снова логика, реакция на силы (например, две из частиц были баундинг сферами капли никотина и ёжика, и последнего разорвало) - поток №1
6. Обход партиклов, перемещение под действием сил - распараллелено
7. Снова логика
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 619
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение vitaly_l » 07.02.2018 17:35:09

Cheb писал(а):Частично переделал под размер чанка 16 Кб, чтобы с запасом уклалось в L1 кэш.
запрещаются счётчики ссылок в _AddRef/_Release
разблокируются счётчики ссылок

Эх примера кода нет (а так всё понятно), а ведь наверняка можно использовать эту фичу не только в игровых движках.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3193
Зарегистрирован: 31.01.2012 16:41:41

Re: Cheb's Game Engine

Сообщение Cheb » 13.02.2018 20:40:33

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

Ностальгирую, хочу игровую логику программировать уже :cry:
Ну, по крайней мере мой фанфик пишется хорошо. Правда Риски Бутс получилась какая-то уж слишком кровожадная. Не переборщил ли я для зеттинга этой франшизы :x

По ходу прикидываю, как бы ещё так свой роман по будущему геймплею Чентры переписать, чтобы перестал быть хардкорным пopно. Пока не получается, хоть и верю, что возможно. Хотя бы до 18+ его прикрутить... [тяжкий вздох]
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 619
Зарегистрирован: 06.06.2005 15:54:34

Пред.

Вернуться в Разработки на нашем сайте

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

Рейтинг@Mail.ru