Доброе время суток! Пытался измерить скорость выполнения команд SSE, а у меня получается, что одна команда выполняется около 4000 тактов. А разве это так? Может у меня счётчик тактов кривой, хотя я проверял вручную, то есть делал цикл, который повторялся несколько сотен тычяч раз и замерял, сколько этот цикл повторяется в секунду, но всё равно получалось, что SSE тормозит. Напишите что у вас выводит программа, у меня 66100. _221712604__001.rar
Maggot Правильнее сказать - ты сам тормозишь SSE Что ты задаешь в vec и matr - целые числа = 100 А нужно что - вещественные single = 100.0, замени и все будет ОК А целое 100 для single-формата это denormal value ~1.4e-43, которое вызывает исключения при mulps и addps - отсюда и тики на два порядка завышены.
Вот всё исправил, но команда movaps тормозит больше всего(без неё 18 тактов, а с ней 74!). Может это только у меня так медленно данные в память записываются. Можете посмотреть, колько у вас тактов показывает, у меня 74. _111737063__002.rar
Maggot > "команда movaps тормозит больше всего" Это не сама movaps тормозит, а последующее чтение movss xmm,[esi+offset] после movaps. Классический partial memory stall из-за невыполнения условий store-to-load forwarding'а - сохраняешь 16 байт, а затем читаешь по 4. Первый movss xmm,[esi] проходит без задержки (выравненные данные берутся напрямую из store-буфера), а следующие оказываются невыравненными и вынуждены ждать пока movaps уйдет в отставку, сохраненные данные попадут в кэш и затем загрузятся из кэша. Подробности см. в IA-32 Optimization. В твоем случае эта фигня проявляется при повторных вызовах Mult_4x4_3x1 в цикле. Если сохранять данные не в тот же вектор vec, а в другой - vec2, то этих задержек не будет.
Maggot Кстати "без нее 18 тактов" - это вдвое заниженное цифры за счет перекрытия соседних циклов при спекулятивном исполнении. Реальная задержка одного прохода составляет ~ 35-40 тактов на P4, что примерно соответствует табличным данным по латентностям IA-32 и А.Фога. Выше крыши не прыгнешь А цикл как видишь все искажает - или в плюс или в минус
All Когда приводите число тиков, надо указывать тип процессора. На разных процах рез-ты могут быть существенно разными. Maggot > "Кстати команды prefetch не работают!" Работают, если использовать их с умом А в твоем случае толку от них никакого. Во-первых, prefetch указывает процессору загрузить данные из ОЗУ в кэш. Если данные уже в кэше, то ес-но толку от этого никакого - кроме потерь нескольких тактов на исполнение prefetch и проверку наличия указанного адреса в кэше. Во-вторых, prefetch загружает в кэш целую линейку данных - 32 байта PIII, 64 байта Атлон, 128 байт P4, т.е. это 4,8,16 циклов шины только на передачу данных, плюс пяток-другой на выборку (зависит от чипсета и таймингов ОЗУ). Учитывая соотношения частот процессора и шины получим не менее 50-100 тактов процессора на загрузку одной линейки. Соответственно чтобы данные успели загрузиться нужно делать prefetch не менее чем за 50-100 тиков. Но это все теория, а в твоем случае prefetch вообще не нужен. Если он что и дает, то только для самого первого прохода - после чего данные преспокойно лежат в кэше. Но во-первых, при самом первом проходе и сам код еще не подготовлен (не построена трасса на P4 или не выполнено предекодирование на Атлоне, не настроен предсказатель переходов, колов и ретов). Во-вторых, ты крутишь цикл аж 10тыс раз, поэтому если при первом проходе и есть доп.задержка в несколько сот тактов, то после деления на число проходов ты ее все равно не увидишь. Совет: убери вообще цикл, а перед вторым rdtsc вставь cld ("магическая" инструкция, не позволяющая rdtsc выполняться раньше чем нужно). Тогда получишь число тиков, близкое к реальному - первые два значения будут завышены (загрузка в кэш, настройка предсказателей), а потом стабилизируются. А 12 тактов - это не реально, это спекулятивное исполнение следующего цикла не дожидаясь завершения предыдущего. Если брать по минимуму, то у тебя 7 зависимых инструкций, каждая в среднем по 2-3 такта на PIII и 4-5 тактов на P4 и Атлоне - вот и считай