SSE тормозит

Тема в разделе "WASM.BEGINNERS", создана пользователем Maggot, 15 авг 2005.

  1. Maggot

    Maggot New Member

    Публикаций:
    0
    Регистрация:
    31 июл 2005
    Сообщения:
    17
    Доброе время суток!



    Пытался измерить скорость выполнения команд SSE, а у меня получается, что одна команда выполняется около 4000 тактов. А разве это так? Может у меня счётчик тактов кривой, хотя я проверял вручную, то есть делал цикл, который повторялся несколько сотен тычяч раз и замерял, сколько этот цикл повторяется в секунду, но всё равно получалось, что SSE тормозит.

    Напишите что у вас выводит программа, у меня 66100.



    [​IMG] _221712604__001.rar
     
  2. readme

    readme New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2005
    Сообщения:
    271
    Адрес:
    Russia
    6500 всреднем, разброс от 6 до 7.4 тыс
     
  3. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Maggot

    Правильнее сказать - ты сам тормозишь SSE ;)

    Что ты задаешь в vec и matr - целые числа = 100

    А нужно что - вещественные single = 100.0, замени и все будет ОК

    А целое 100 для single-формата это denormal value ~1.4e-43, которое вызывает исключения при mulps и addps - отсюда и тики на два порядка завышены.
     
  4. Maggot

    Maggot New Member

    Публикаций:
    0
    Регистрация:
    31 июл 2005
    Сообщения:
    17
    Вот всё исправил, но команда movaps тормозит больше всего(без неё 18 тактов, а с ней 74!). Может это только у меня так медленно данные в память записываются. Можете посмотреть, колько у вас тактов показывает, у меня 74.

    [​IMG] _111737063__002.rar
     
  5. readme

    readme New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2005
    Сообщения:
    271
    Адрес:
    Russia
    33 стабильно почти
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    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, то этих задержек не будет.
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Maggot

    Кстати "без нее 18 тактов" - это вдвое заниженное цифры за счет перекрытия соседних циклов при спекулятивном исполнении. Реальная задержка одного прохода составляет ~ 35-40 тактов на P4, что примерно соответствует табличным данным по латентностям IA-32 и А.Фога. Выше крыши не прыгнешь ;) А цикл как видишь все искажает - или в плюс или в минус :dntknw:
     
  8. R_NEW

    R_NEW New Member

    Публикаций:
    0
    Регистрация:
    6 май 2005
    Сообщения:
    86
    Адрес:
    Россия
    У меня около 75
     
  9. Maggot

    Maggot New Member

    Публикаций:
    0
    Регистрация:
    31 июл 2005
    Сообщения:
    17
    Когда предварительно загружаю в кэш, то 12 тактов. Кстати команды prefetch не работают!
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    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 и Атлоне - вот и считай