1. Си / Говнокод #23176

    +5

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    inline int ms_001(int x){ return    x                                                ;}    //  x * 1
    inline int ms_002(int x){ return    x<<1                                             ;}    //  x * 2  
    inline int ms_003(int x){ return    x<<2 - x                                         ;}    //  x * 3  
    ...
    inline int ms_799(int x){ return    x<<10 - x<<8 + x<<5 - x                          ;}    //  x * 799
    inline int ms_800(int x){ return    x<<10 - x<<8 + x<<5                              ;}    //  x * 800
    
    // массив указателей 
      int ( *mult_shift[800] ) (int) = {
                                            ms_001,              
                                            ms_002,
    ...
                                            ms_799,
                                            ms_800  };

    Очень быстрое целочисленное умножение

    Запостил: fse, 12 Июля 2017

    Комментарии (13) RSS

    • > Очень быстрое
      > x<<10 - x<<8 + x<<5 - x
      gcc с -O3 разворачивает эту поебень в 8 инструкций. Сразу видно, что быстрее одного imul!
      Ответить
      • Странно, что гцц не оптимизнул эту поебень в imul. Аппаратный умножитель работает всего на чуточку медленней сложения ;)
        Ответить
    • О, тут всё глубже. Файл присутствовал в проекте, но не использовался. По соображениям "надают по шапке", остальной код публиковать низя, но уверяю, он великолепен.
      Загадка:
      1. Почему ЭТОТ код не работает в принципе
      2. Почему не инлайнится
      3. Почему описан в cpp-файле
      4. Почему файл существует и впаривается разным заказчикам (возможны варианты)
      Ответить
      • 2. Инлайн функции и указатель на эту функцию, тут инлайн не прокатит.
        3. Наверное какой-то жутко оптимизированный модуль
        4. Я и не такое видел как заказчикам впаривают.
        Ответить
      • >4. Почему файл существует и впаривается разным заказчикам (возможны варианты)

        Возможно существуют абсолютно идиотские компиляторы, которые подобную замену умножения на сдвиг осуществить не могут вообще ни с какимии флагами? Или заказчиков пытаются убедить в существовании таких компиляторов, и потом это впаривают?

        >1. Почему ЭТОТ код не работает в принципе

        Не работает в смысле не используется? Возможно потому, что нахуй не надо такое использовать: компиляторы и так умеют умножение в сдвиги оптимизировать

        Эта хренота с умножением через сдвиги вот описана http://z0mbie.daemonlab.org/asm.html#e
        Ответить
        • А, и да, учитывая что это говно не будет инлайниться т.к. это массив из указателей на функции, накладные расходы этого говна возможно будут даже больше, если просто воспользоваться аппаратной инструкцией умножения. Так что это может иметь смысл использовать, если аппаратной инструкции умножения в принципе не предусмотрено. Но если так, то в таких компиляторах под такие платформы НУ ТОЧНО реализовали алгоритм умножения двух чисел через сдвиги, так что такой код совершенно точно нахуй там не нужен.
          Ответить
        • > которые подобную замену умножения на сдвиг осуществить не могут вообще ни с какимии флагами?

          Я так понимаю, это "суперкомпиляция вручную". Компилятор заоптимизирует умножение только в том случае, если в коде будет стоять константа. Если хочется выполнить оптимизацию в рантайме, компилятор тебе не поможет. Поэтому автор кода выписал специализации для каждого значения аргумента и сделал табличку для диспатча в рантайме. Жаль, но его коварный план обречён на провал по понятным причинам.

          Думаю, даже если заменить вызов функции по указателю на свитч-кейс по x, инструкция умножения всё равно будет ощутимо быстрее.
          Ответить
        • > в смысле не используется
          Имеется в виду дает неверный результат для всех множителей кроме степени двойки...
          Ответить
          • Гхм, кто еще не понял - советую попробовать вызвать ms_799(10) и увидеть что ответ не 7990. Ибо приоритет выполнения операторов си не зависит от числа пробелов.
            Ответить
    • 5. почему китайцам платят за строки кода
      Ответить
    • Починил
      template <int by>
      struct mul;
      
      template <> struct mul<1>   { int operator()(int x) const { return x;          } };
      template <> struct mul<2>   { int operator()(int x) const { return x << 1;     } };
      template <> struct mul<3>   { int operator()(int x) const { return x << 2 - x; } };
      // ...
      template <> struct mul<800> { int operator()(int x) const { return x<<10 - x<<8 + x<<5; } };
      
      template <int by>
      int mul_by(int x) { mul<by> f; return f(x); }
      Писать inline и тут же брать указатель на функцию — это, конечно, сильно.
      Ответить

    Добавить комментарий