Pull to refresh

Comments 13

UFO just landed and posted this here
Стоило включить PGO (profile-guided optimisation) для того, чтобы оптимизация выполнялась для типичного кейса, когда вычисляется сумма 20 слов, а не миллионов.

Для невыравненного доступа к данным мы используем каст в такую структуру
struct unaligned_i32 {
  int32_t value;
} __attribute__((packed));

Получается более оптимально, чем с memcpy — компилятор не делает лишнего копирования на архитектурах с невыравненным доступом.
Да, кстати вот получается __attribute__((packed)) решает проблему, а стандартизированный _Alignas(...) не может выравнять меньше чем на естественную границу.

Вместо того чтобы скрывать особенности архитектуры компилятор выворачивает их мехом наружу.
Вот за это современный C++ мне не нравится

Для абстракции архитектуры полно других языков программирования, они гораздо лучше справляются с этой задачей. Возможно Вы выбрали не тот язык, если это имеет решающее значение?
uint64_t sum(const char * p, size_t nwords)
{
    uint64_t res = 0;
    uint64_t data[4] = 0;
    size_t i = 0;
    while(i < nwords*4) 
    {
        data[0] += (uint64_t)p[i++];
        data[1] += (uint64_t)p[i++];
        data[2] += (uint64_t)p[i++];
        data[3] += (uint64_t)p[i++];
    }
    res = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
    return res;
}

Может и не оптимально, зато весело :-D

Вот только это не везде сработает. Т.к. (uint64_t)p[i++] — разыменование невыравненного указателя

Вообще-то это приведение char к uint64_t, а не работа с указателями. Можно и без этого наверное — компилятор сам должен привести если к uint64_t прибавляем char.
И да, ошибочка, объявлять надо так:
uint64_t sum(const unsigned char * p, size_t nwords)
Иначе при преобразовании отрицательных char получится не то, что хотелось бы.
for (size_t i = 5; i < size / 4; i++) {
        sum += q[i];


Предполагается, что размер заголовка всегда кратен 4?

А по поводу использования инструкций sse.
Недавно у себя при сборке проекта clang'ом 3.8 под x86 также на это наступили.
clang в случае зануления через memset активно использует sse.
Временно решили проблему, используя опцию -mstackrealign
Удивляет, что выравнивание до сих пор отвратительно стандартизировано даже в новейших редакциях C++. И это при том, что почти любые SSE-инструкции требуют выровненных данных. Зато всякий бред из помойки под названием boost тащат.

Отправьте уже старпёров из комитета на пенсию, они безнадёжно застряли в 80-х.

а один раз скопировать в выровненный буфер, и потом целиком посчитать не?

Sign up to leave a comment.

Articles