Войти
ПрограммированиеФорумОбщее

C++, низкий уровень, оптимизация быстродействия.

Страницы: 1 2 311 12 Следующая »
#0
10:36, 13 фев. 2019

Пытаюсь портировать свой 2D движок на x64, но с переходом на x64 потерян инлайн асм.
Я в некотором шоке от потери быстродействия при переводе асм-вставок на C.

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

+ Например, сумма теперь выглядит так
+ Вот Clamp
+ А так эта функция выглядела с асм-вставками

На этом я пятикратно теряю быстродействие...

Для пробы на функции полусуммы я пошёл на ухищрение, ценой потери одного бита в результате заменил это:

for (int t = 0; t < 4; t++)
{
  *((byte*)dest + (x + y * wd) * 4 + t) = (*((byte*)dest + (x + y * wd) * 4 + t) + *((byte*)src + (x + y * ws) * 4 + t)) >> 1;
}
на это:
*(dest + x + y * wd) = ((*(dest + x + y * wd) & 0xfefefefe) >> 1) + ((*(src + x + y * ws) & 0xfefefefe) >> 1);
Всё равно, потеря по сравнению с MMX примерно 1.5 раза, а ведь такие ухищрения далеко не везде возможны.

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

#1
(Правка: 11:05) 11:04, 13 фев. 2019

Для использования асма, можно просто скомпилить объектники в MASM64 и прилинковывать их к проекту на С.
Для использования SIMD можно просто юзать интринсики типа _mm_adds_epi8:

__m128i m1, m2;

....

_mm_adds_epi8(m1, m2);

....
Список тут, ммх не поддерживается.

#2
11:17, 13 фев. 2019

the trick
> Список тут
Векторные операции лучше смотреть здесь.
Ну и да, MMX устарел с выходом SSE2, а в x64 режиме он есть гарантированно.

#3
11:33, 13 фев. 2019

}:+()___ [Smile]
> Векторные операции лучше смотреть здесь.
Ну да, но если нужно по всем интринсикам типа __readgsqword то на мсдн более полное.

#4
(Правка: 12:56) 11:37, 13 фев. 2019

Давай начнём с простого, __m64 _mm_adds_pu8(__m64 a, __m64 b). Это интринсик основной операции, на которой основан твой асм код paddusb. Она никуда не делась. Надо просто переписать алгоритм тот же алгоритм интринсиками. Лучше всего уже на SSE/SSE2 (_mm_adds_epu8). Плюс сам код на сях написан сильно не оптимально, ты делаешь очень много лишних операций внутри циклов.

+ По сути ты пишешь это:

Но и это ещё можно соптимизировать, потому что y<h, x<w это не идеал, лучше декрементные счётчики циклов.

+ Итого получаем на плюсах:
+ Студийный x86 ассемблер выдаёт:
+ Студийный x64 ассемблер выдаёт:

Сравни, кстати со своим ассемблером. Он у тебя тоже сильно далёк от идеала. Те же сдвиги ты делаешь вручную, когда они вообще не нужны на самом деле.

P.S. Грамотно написанный код + интринсики зачастую оптимальнее ручного ассемблера. Хотя в данном случае внешний цикл x86 мне сильно не нравится. x64 наоборот долго запрягает, да быстро едет. И ещё внешний цикл походу получился больше потому, что он не учитывает, что src+=ws делать не надо. Из сишного кода это не следовало. Из моего можно просто выкинуть src+=ws и наслаждаться существенно сжавшимся кодом.

#5
11:49, 13 фев. 2019

Truthfinder
> ты делаешь очень много лишних операций внутри циклов
Я пробовал выносить, лучше не становится, очевидно компилятор сам выносит.
Truthfinder
> Давай начнём с простого
Именно это мне сейчас и нужно! Как доберусь до компьютера с компилятором, буду пробовать.
Кстати, какая минимально студия поддерживает интринсики?
Могу ли я всё отлаживать в x32, а потом перекомпилировать в x64? Просто мне удобно делать поэтапно, часть кода оставляя старым. Или в x64 интринсики другие?

#6
12:07, 13 фев. 2019

Mikle
> Я пробовал выносить, лучше не становится, очевидно компилятор сам выносит.

Вот таких конструкций не должно быть: *((byte*)dest + (x + y * wd) * 4 + t)

> Кстати, какая минимально студия поддерживает интринсики?

Вот хз, я не помню с какой студии начал их использовать. Вроде с 2012. Если есть intrin.h то поддерживает. В теории чуть ли не с 6, может с 7.

> Могу ли я всё отлаживать в x32, а потом перекомпилировать в x64? Или в x64 интринсики другие?

Да, интринсики идеально подходят для написания одного кода под x86/x64 платформы. Выше я добавил пример. Один код собран в x86 и x64.

#7
12:14, 13 фев. 2019

Можно вычисления на OpenCL вынести - получишь ускорение в 10 раз. Но есть особенность: с OpenCL в идеале все данные лучше сразу в видеопамяти хранить.

#8
12:15, 13 фев. 2019

Truthfinder
А чем декрементные счетчики у циклов лучше?

#9
(Правка: 12:22) 12:17, 13 фев. 2019

BingoBongo
> Можно вычисления на OpenCL вынести - получишь ускорение в 10 раз. Но есть
> особенность: с OpenCL в идеале все данные лучше сразу в видеопамяти хранить.

Я так понял движок графический. Не проще тогда уже сразу Vulkan? Вроде как здесь софтовость это фича. Тем более мы знаем, что ТС HW графику умеет.

#10
(Правка: 12:21) 12:20, 13 фев. 2019

Vlad2001_MFS
> А чем декрементные счетчики у циклов лучше?

+ inc
+ dec

Как видим разница в +1 инструкцию внутри цикла гарантирована.

#11
12:51, 13 фев. 2019

Truthfinder
> Я так понял движок графический. Не проще тогда уже сразу Vulkan? Вроде как
> здесь софтовость это фича. Тем более мы знаем, что ТС HW графику умеет.
Дело даже не в фиче, этот движок не столько для игр, сколько для инструментов.
Truthfinder
> декрементные счетчики
Попробую. А с кэшем проблем не будет?

#12
(Правка: 12:54) 12:53, 13 фев. 2019

Mikle
> Попробую. А с кэшем проблем не будет?

Во-первых как можно видеть по коду переменные счётчики в нашем случае в вычислениях не участвуют. Во вторых на новых архитектурах неважно куда двигаться по памяти. Это в доке Intel написано. Вроде которая optimization manual.

#13
12:59, 13 фев. 2019

Truthfinder
> переменные счётчики в нашем случае в вычислениях не участвуют
Я не об этом
Truthfinder
> на новых архитектурах неважно куда двигаться по памяти. Это в доке Intel написано
А об этом.

#14
13:18, 13 фев. 2019

Mikle

Это поверхностное улучшение, в лоб. Если обрабатывать по несколько пикселей за раз, можно поднять производительность в разы не напрягаясь. SSE - по 4 пикселя, AVX - по 8 пикселей.

Страницы: 1 2 311 12 Следующая »
ПрограммированиеФорумОбщее