Обновить

Комментарии 12

В итоге x500 прирост за счёт того, что std::cin заменил на mmap и x1,1 за счёт остального. Причём и первая замена несправедлива: в файле текст 122 127 89 ..., а в решении двоичный файл с байтами. Для справедливости переводчик мог бы показать прирост скорости только от замены std::cin с текстовым файлом на mmap с двоичным файлом

оптимизированное решение работает со стандартным вводом

Вы можете посмотреть условие и проверить свое решение на https://highload.fun/tasks/5 . там бинарные данные идут на вход. Замена std::cin на mmap дает x250 ускорение. А дальше волшебство и танцы с бубном, чтобы приблизиться к лидеру.

Мдас… чтобы ассемблер уверенно обходил все эти «умные компиляции», в наше время надо прямо уже конкретно жестить :)

С другой стороны — такого внимания требует 1% кода (но рискующий сожрать 99% времени выполнения). Тут можно и расщедриться. В этом плане ничего не изменилось :)

Решение, которое мы представим, работает в 550 раз быстрее следующей тривиальной программы.

Не, я конечно понимаю, что надо привлечь внимание, но это уже перебор. Если хоть как-то интересует производительность, это самый медленный способ читать из файла.

Если использовать обыкновенный read, то наивная реализация работает всего лишь в 5 раз медленнее оптимизированной. И это, конечно, тоже очень неплохо, но сенсации уже не получится.

#include <unistd.h>
#include <iostream>

int main(int argc, char **argv)
{

uint64_t count = 0;
size_t bufsize = 1024*4*256;
uint8_t buf[bufsize];
while(true) {
  ssize_t nread = read(0, buf, bufsize);
  if(nread <= 0) break;
  for(unsigned ii = 0; ii < nread; ++ii) {
    if (buf[ii] == 127) {
        ++count;
    }
  }
}
std::cout << count << std::endl;
return 0;
}
$ g++   -mavx2 -O3 simddumb.cc -o simddumb
$ time ./simddumb < testf.bin 
53616490

real	0m3,660s
user	0m2,474s
sys	0m1,185s
$ time ./simd < testf.bin 
53616490

real	0m2,150s
user	0m0,500s
sys	0m1,650s

Размер testf.bin 13GB

mmap это конечно уже не совсем наивная реализация, но надо для начала испытать с mmap и прочими оптимизациями, перед нырянием в ассемблер

Там с подсчётом довольно странная ситуация.

Лучшее решение - 13к "попугаев".

1. Ваше решение - 155к (в 12 раз хуже)
2. То же с mmap - 79к (в 6 раз хуже)
3. Mmap + массив счётчиков + full unroll внутреннего цикла - 58к (в 4.5 раза хуже)
// решение с многопоточностью - предсказуемо ничего не даёт (1CPU в условии).

Надо заметить, что на моём 7800x3d (c AVX2) - последнее решение почти догнало asm-код.

Я подозреваю, что там какие-то артефакты измерений и лучшие решения это абузят (например(не обязательно это) меряют system-time + user-time -- тогда абузом будет: и prefetrch + nanosleep, т.к. nanosleep не попадёт в user/system time и по-сути подкачку данных из памяти в кэш мы не подсчитаем)

Похоже на челендж highload fizzbuzz с кодгольфа.

НЛО прилетело и опубликовало эту надпись здесь

При последнем чтении буфер может заполниться не до конца, и часть байтов с прошлой итерации будут обработаны ещё раз.

НЛО прилетело и опубликовало эту надпись здесь

В ней используется только AVX2, а AVX512 не используется.

А если использовать AVX512, то ещё в разы быстрее станет?

Спасибо за интересную ссылочку... Пошевелил мозгами чутка, занял 7е место в лидерборде по гошечке :)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации