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

    −11

    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
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    void *memcpy(void *__dest, __const void *__src, size_t __n)
    {
            int i = 0;
            unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
    
            for (i = __n >> 3; i > 0; i--) {
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
            }
    
            if (__n & 1 << 2) {
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
                    *d++ = *s++;
            }
    
            if (__n & 1 << 1) {
                    *d++ = *s++;
                    *d++ = *s++;
            }
    
            if (__n & 1)
                    *d++ = *s++;
    
            return __dest;
    }

    Царский анролл в memcpy, прямиком из ядра Linux

    http://lxr.free-electrons.com/source/arch/arm/boot/compressed/string.c

    Запостил: j123123, 30 Апреля 2017

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

    • показать все, что скрытоя нащупал ядро когда делал тебе фистинг
      а ты говоришь линукс
      Ответить
    • А почему __n не const?! Неоптимизированно! Расстрелять!
      Ответить
    • показать все, что скрытоА зачем они по байтику копируют? Какими-нибудь интами не быстрее?
      Ответить
      • > Какими-нибудь интами не быстрее?
        Не все ARM'ы умеют читать и писать невыровненные инты. Видимо, автор надеется на то, что гцц сам свернёт эти 8 копирований в одно большое, елси платформа умеет в невыровненный доступ.
        Ответить
        • показать все, что скрытоМожно было бы хвост и голову по байтику, а большую часть выровненными интами.
          Ответить
          • Не прокатит. Нет гарантии, что src и dest одновременно выровняются.
            Ответить
            • показать все, что скрытоНадо src и dst кастануть в size_t и найти остаток от деления на какой-то выровненный инт, и если остаток от деления и там и там одинаков, то тогда можно
              Ответить
              • Ну и получится странная херня, которую даже забенчить толком нельзя. В четверти случаев работает быстро, в половине - помедленнее, в последнем - вообще лагает...

                З.Ы. Ну хотя, блоки в куче обычно выровнены. Так что хотя бы для них будет пошустрее копировать.
                Ответить
                • Т.е., ради того, чтобы забенчить было проще, надо писать код, который в 4/4 случаев лагает?
                  Ответить
                • может имеет смысл тогда проверять размер? Аля на каких-нибудь 5 элементах быстрее по байтику скопировать, а на 1к можно и выравнивание проверить
                  Ответить
                  • показать все, что скрытоДа кстати, даже если там при копировании чтение-запись происходит по неразрешенным смещениям, ну типа
                    addr|00|01|02|03|04|05|06|07|..|A0|A1|A2|A3|A4|A5|A6|A7|
                        | uint32t_1 | uint32t_2 |..| uint32t_3 | uint32t_4 |
                        |  |  |  |  |  |  |  |  |..|  |  |  |  |  |  |  |  |
                    Из  |  |^^|^^|^^|^^|^^|^^|^^|..|  |  |  |  |  |  |  |  |
                    В   |  |  |  |  |  |  |  |  |..|  |  |^^|^^|^^|^^|^^|^^|

                    То тоже можно что-нибудь придумать, например читать uint32t_1, маской убрать четвертый байт, сдвинуть потом на 1 байт вправо (и сохраняем, этот байт нам потом понадобится) и записать в uint32t_3, после чего читаем uint32t_2, сдвигаем вправо на 8(сохранив опять-таки вытолкнутый байт), и тот старый байт что был сохранен на предыдущем этапе из uint32t_1 - мы его суем в старший байт этой хни, и потом записываем в uint32_4
                    Ответить
              • > кастануть в size_t
                В uintptr_t всё-таки.
                Ответить
            • показать все, что скрытоТочняк. А я и не подумал. Какой же ты умный, бормондяша.
              Ответить
      • > А зачем они по байтику копируют? Какими-нибудь интами не быстрее?

        ключ находится в названии директории файла: "arm/boot".

        это часть бутстрапа, и к самому ядру линуха имеет мало отношения.

        похоже на компромис между размером кода и производительностью.

        типы из free-electrons умееют бенчить. они достаточно хорошо известны в кругах встроенного линукс/арм.
        Ответить
        • показать все, что скрытомой член хорошо известен в кругу местных пассивов
          Ответить
        • > бутстрапа
          Тогда не будет ли вся эта магия с анроллом стрельбой из пушки по тараканам? Стоит ли все это городить ради куска, который проживёт пару-тройку миллисекунд, настроит окружение и сгорит в атмосфере?
          Ответить
          • > Стоит ли все это городить ради куска, который проживёт пару-тройку миллисекунд

            копирование распаковоного кернела длится 100-500мс на мелких системах. почему бы и не сэкономить несколько десятков миллисекунд, если это и не так сложно?

            и что значит "городить" - раз написал, и будет работать годами. это не код на котором все будут спотыкаются, или в нем что-то будет ломатся.
            Ответить
    • ну правильно. Если целевая платформа поддерживает копирование по 8 байт, будет за раз 8 байт гонять. А если только по байту, оптимизнет в цикл
      Ответить
    • > __n & 1 << 2
      Хоть бы скобочки расставили...
      Ответить
    • показать все, что скрытоПочему кстати никто не вспомнил itt про ключевое слово restrict?
      Ответить
      • > restrict
        Линус запретил поди. Он же всегда выступал против агрессивных оптимизаций, которые ломают кривой код.
        Ответить

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