Подскажите ссылки на документы (на русском или английском) с информацией о длительностях и условиях возможности/невозможности конвейеризации различных SSE-команд (movaps, movups, mulps, addps, shufps). Пытаюсь в поисковике - видать не так спрашиваю, получаю всякую фигню. Проц - ну, скажем, Core2Duo. Хотя интересно было бы узнать, насколько разнится с другими процами с поддержкой SSE.
Вот тут описано. http://www.intel.com/Assets/PDF/manual/248966.pdf А также A.Fog можно почитать. Кстати он на wasm в переведенном виде лежит.
После прочтения интеловского и фоговского руководств по оптимизации все равно остался вопрос. И там и там явно говорится, что инструкция MOVUPS для загрузки SSE-регистра с невыровненного адреса памяти работает существенно медленнее выровненной MOVAPS. Но насколько медленее - непонятно. Просто советуют использовать чтение по выровненным адресам даже в неизбежных случаях, вручную выравнивая содержимое, например, с помощью инструкции PALIGN (SSSE3). Но вот мой случай - мне необходимо выполнять свертки по ядрам, занимающим достаточно большой диапазон смещений, но очень разреженным, то есть, большинство из коэффициентов равны нулю. Что-нибудь типа y=x*k1 + x[i+50]*k2 + x[i+51]*k3 + x[i+100]*k4 Количество и положения ненулевых членов ядра свертки заранее неизвестно, поэтому полный анролл сделать не могу, в любом случае нужен цикл по ненулевым членам, описываемым массивом пар (коэффициент, смещение). Очевидно, при решении "в лоб" чтения по невыровненным адресам не избежать. Но у лобового решения есть преимущество - короткий цикл, полностью помещающийся в Instruction Queue и фактически работающий в полностью декодированном виде. Для использования выровненного чтения придумался такой вариант: сделать анролл на четверки смежных смещений, искусственно добавив смежные смещения с нулевыми коэффициэнтами, так, чтоб вся четверка вычислялась из однократно прочитанной из памяти восьмерки элементов по выровненному адресу. Но так в каждом цикле имею 4 обязательных умножения (чаще всего три из них - на нули). Обходить нулевые умножения условными переходами практически бесполезно из-за спекулятивного выполнения при неверном предсказании переходов. Воспользоваться PALIGN, SHUFPS, MOVHPS также не получается, поскольку заранее неизвестно, насколько надо выравнивать, а эти команды требуют immediate. Как бы узнать, насколько неэффективным является чтение по невыровнненному адресу, не проводя эксперимента?
Это зависит от того как эти данные располагаются или не располагаются в кэшах. А так задержка перед тем как можно будет исполнять следующую макроинструкцию при выровненных данных меньше в 2 раза. Так как не надо делать второй цикл чтения. Скорее всего через быстрое преобразование Фурье будет быстрее.
Тоже так думалось изначально. Смущают заявления интела (и даже пример через palign), что лучше вручную читать выровненные данные и потом искусственно выравнивать. Ведь так все равно будет второй цикл чтения, плюс еще явные инструкции по выравниванию, которые могут повлиять в фронт-энд части. Хотя, может они имели в виду, что прочитанными данными можно воспользоваться еще раз "не отходя от кассы" для смежных смещений... Но если Вы правы, то не так страшен movups, как его малюют...
Dmitry_Milk Видать плохо смотрел, т.к. у Фога в instruction_tables приведены конкретные цифры latency и throughput отдельно для movaps\d и movups\d для разных процев
leo, Вы правы. Фоговские таблицы я не смотрел, читал только файл по оптимизации асм-процедур, поскольку таблицы latency и throughput для разных процов видел уже в интеловской доке. Посмотрел сейчас Фоговские таблицы. Цифры относительно инструкций MOVAPS и MOVUPS соответствуют интеловским. Reciprocal throughput MOVAPS xmm,m128 и MOVUPS xmm,m128 упирается в read-порт (конечно, при кэш-попадании), и соответственно у MOVUPS строго в два раза больше.