Отмена умножения на единицу во время выполнения

Тема в разделе "WASM.BEGINNERS", создана пользователем Camarada, 12 апр 2008.

  1. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    KeSqueer
    Собственно я руководствовался вот этой фразой, когда отвечал:
    http://www.wasm.ru/forum/viewtopic.php?pid=197711#p197711
    :)
    Так что сохранять руками регистры нет необходимости. Коду за пределами asm-вставки хуже не станет, если их не сохранять.
     
  2. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Да...... вижу противоположные точки зрения.
    Нашел статейку.
    Код (Text):
    1. При написании кода на inline-ассемблере Visual C++ следует помнить некоторые моменты. Во-первых, значения регистров не передаются между ассемблерными вставками. Например, если в ассемблерной вставке ты установил eax в 1, то в следующей ассемблерной вставке eax не обязательно будет равно 1 (смотри листинг 5).
    2.  
    3. Во-вторых, нужно быть осторожным с регистрами и стеком. В середине ассемблерных вставок нельзя менять регистры ds, ss, sp, bp и флаги. Если эти регистры все-таки меняются, перед выходом из ассемблерной вставки их нужно обязательно восстановить. Что касается стека, то тут нужно соблюдать правило, которое гласит: если в ассемблерной вставке нечто ложится на стек, то в той же ассемблерной вставке это «нечто» должно со стека сниматься.
     
  3. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Да, как мне произвести умножение double?
     
  4. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Camarada
    Что значит как?
    double a = 6.78, b = 1.91;
    double c = a*b;
    или имелось в виду на асме?
     
  5. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Вот вот, можно было и догадаться.
     
  6. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Я бы это в данном случае лучше доверил компилятору C
     
  7. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Блин, я пишу код ускоряющий выше описанные операции на ассемблере. Я уже нашел как, не трудитесь.
     
  8. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Camarada
    И как ускорение?
     
  9. _G3

    _G3 New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    41
    Адрес:
    Russia
    Camarada
    Две недели уже оптимизируешь. Пора результаты показывать.
    Хотелось бы увидеть какой код был на Си и что ты с ним сделал на асме.
     
  10. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Я писал уже код, сообщение 33. Я новичек в ассемблере, поэтому не знаю инструкций толком, тем более сопроцеесора, так как мне нужно выполнять умножение с плавающей точкой, мне нужно знать эти самые инструкции.
    Так долго оптимизирую, потому что это сейчас не первоочередная задача, а вот вскоре может пригодиться.
    Результаты пока плачевные, но дело в том, что я использовал __asm вставки внутри цикла, не думаю, что это хорошо сказалось на производительности. Обязательно отпишу, когда будут результаты.
    Если можно, дайте ссылочку, где описаны инструкции процессора и сопроцессора (У меня старый Селерон 2,4 ГГц). И где можно прочитать про спариваемость инструкций.
     
  11. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
  12. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Кстати вот код, который генерит компилятор MSVS (я сначала пробовал для целых чисел)
    Код (Text):
    1. mov     eax,dword ptr [j]
    2. movsx       ecx,byte ptr [ebp+eax-801Ch]
    3. mov     edx,dword ptr [i]
    4. movsx       eax,byte ptr [ebp+edx-4014h]
    5. imul        ecx,eax
    6. add     ecx,dword ptr [sum]
    7. mov     dword ptr [sum],ecx
    А вот мой.
    Код (Text):
    1. __asm
    2. {
    3.     mov esi, i
    4.     movsx cx, w[esi]
    5.     mov esi, j
    6.     movsx ax, a[esi]
    7.     and cl, ch
    8.     xor ax, cx
    9.     sub ax, cx
    10.     cwde
    11.     add eax, sum
    12.     mov sum, eax
    13. }*/
    Мой медленнее((((
     
  13. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    А вот и код с циклами. Он чуть побыстрее, но все равно очень сильно проигрывает коду компилера.
    Код (Text):
    1. __asm
    2. {
    3.         xor edi, edi ; edi выполняет роль счетчика i. esi - j
    4. icyc:
    5.         cmp edi, N ;N - количество итераций (константа), проверка выхода
    6.         jnl iend ; Если i>= N, выходим из цикла
    7.         xor ebx, ebx ; Переменная сумматор
    8.         xor esi, esi; Обнуляем j
    9. jcyc:       cmp esi, N; Сравниваем
    10.         jnl jend; Если j<=N, выходим из цикла j
    11.         movsx cx, w[edi] ; Значение (-1 или 1) в cx с расширением до слова
    12.         movsx ax, a[esi] ; Значение массива преобразуемых величин в ax
    13.         ;Типы массивов: char[N]
    14.         and cl, ch ;cx = FFFF либо 0000
    15.         xor ax, cx ; ax = !a[esi] либо a[esi]
    16.         sub ax, cx; ax = - a[esi] либо ax = a[esi]
    17.         cwde ; eax = расширенное до DWORD слово ax
    18.         add ebx, eax; К переменной сумматору добавляем вычисленное значение
    19.         inc esi ; j++
    20.         jmp jcyc ; В начало цикла
    21. jend:
    22.         mov b[edi], ebx ; Вычесленную сумму в выходной массив
    23.         inc edi ; j++
    24.         jmp icyc ; В начало цикла
    25. iend:
    26. }
    Видимо все бесполезно(((((
    Умножение занимает слишком мало тактов???
     
  14. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    Camarada
    комментарии в коде никогда не бывают лишними, и
    Код (Text):
    1.         mov sum, 0
    2.         xor esi, esi
    3. можно поменять на
    4.         xor esi, esi
    5.         mov [sum], esi
    P.S. попробуйте улучшить код компилятора
     
  15. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Сейчас все отредактирую
    К сожалению, код компилятора выполняет умножение, а я как раз эту часть и хочу улучшить.
     
  16. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    Код (Text):
    1. __asm
    2. {
    3.         xor edi, edi;
    4. icyc:
    5.         cmp edi, N
    6.         jnl iend
    7.         xor ebx, ebx
    8.         xor esi, esi
    9. jcyc:       cmp esi, N
    10.         jnl jend
    11.         inc esi
    12.         jmp jcyc
    13. jend:
    14.         inc edi
    15.         jmp icyc
    16. iend:
    Как это ни печально, этот код (просто двойной цикл без операций внутри) работает дольше, чем код с умножением компиллятора.
     
  17. Nero_n

    Nero_n New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2008
    Сообщения:
    33
    С измерением времени нигде не ошибся? А то я как-то полдня с квадратными глазами ходил и удивлялся могуществу чудесного компилятора... Потом обнаружил, что время брал не с тем знаком >_<
     
  18. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Код (Text):
    1.     mov ebx, [N]
    2.     mov edi, ebx
    3.     i_loop:
    4.     mov esi, ebx
    5.     xor edx, edx
    6.     j_loop:
    7.     mov cl, w[edi-1]
    8.     mov al, a[esi-1]
    9.     xor al, cl
    10.     sub al, cl
    11.     movsx   eax, al
    12.     add edx, eax
    13.     dec esi
    14.     jnz j_loop
    15.     mov b[edi*4-4], edx
    16.     dec edi
    17.     jnz i_loop
    попробуй так
    кстати, неправильно писать mov b[edi], ebx, a mov b[edi*4], ebx afaik
     
  19. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    перечитал топик.
    Camarada
    Код (Text):
    1. for (int i=0; i<N; i++)
    2. {
    3.     double sum=0;
    4.     for (int j=0; j<N; j++)
    5.         sum+=incom[j]*wa[i][j];
    6.     outcom[i]=sum;
    7. }
    8. /*wa[i][j] - (char**)2мерный массив NxN функций Уолша.
    9. incom  -  (double*) как раз наш преобразуемый массив.
    10. outcom - (double*) посчтитанное преобразование*/
    1. обращаться к данным в памяти лучше не столбцам, а по строкам - из-за кеширования;
    2. компилятор по-прежнему рулит ;)
     
  20. Camarada

    Camarada New Member

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    24
    2KeSqueer. Проблема серьезнее. При прогоне цикла под директивой __asm пустой цикл работает в два раза больше, чем цикл, работающий с умножением, то есть я вообще не вижу смысла дергаться. Самые приемлимые результаты получаются при коде.
    Код (Text):
    1. for (int i=0; i<N; i++)
    2. {
    3.     register int sum = 0;
    4.     register short ww = w[i];
    5.     char* pw = (char*)&w;
    6.     ww = short(((*pw))  & (*(pw + 1))) ; это наше and al,ah (жутковато да))))
    7.     for (int j=0; j<N; j++)
    8.     {
    9.         register a = ww ^ a[j];
    10.         a -= ww;
    11.         sum += a;
    12.     }
    13. }
    Может вместе оптимизируем его еще :derisive:

    При N = 2^15 код с умножением, который кстати теперь (для простоты) выглядит так:
    Код (Text):
    1. for (int i=0; i<N; i++)
    2. {
    3.     int sum = 0;
    4.     for (int j=0; j<N; j++)
    5.     {
    6.         sum += a[j]*w[i];
    7.     }
    8.     b[i] = sum;
    9. }
    выполняется в среднем (последние измерения) за 1.28 секунды, тогда как первый - за 2.2 секунды :-(