LINUX.ORG.RU

Производительность; илитный запил оптимальных реализаций и основы матчасти.

 , , ,


21

17

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

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

Изначально я хотел написать про то: что такое бесплатные вычисления на примере is_range() + сумма елементов массива, но тут выявилась смешная особенность, поэтому пока без is_range().

Начнём с простого - сумма елементов(float) массива. Как написать её быстро? Обычный крестопоц сделает так:

auto summ = accumulate(begin(vec), end(vec), 0.)

Этот код выдаёт 5.6GB/s(мы всё бенчим в л1д 32килобайта массив). Казалось бы, если бы мы слушали всяких «гуру», которые нам говорят: accumulate() - оптимизирован, «ты что умнее создатели stl"а?», «конпелятор умнее тебе - сам всё делает оптимально», «руками что-то делать слишком сложно и не нужно» - то мы бы там и остались с этими 5.6ГБ, но мы пойдём дальше и поймём почему так, и является ли это тем, что намн ужно.

Но посмотрев на код - он не векторизован:

	addq	$4, %rdx
	vcvtss2sd	-4(%rdx), %xmm2, %xmm2
	vaddsd	%xmm2, %xmm1, %xmm1

Почему? Патамучто это основная флоатпроблема: Он не ассоциативен - флоат не имеет в себе точных представлений всех чисел входящих в диапазон его «представления» т.е. порядкопроблемы.

Поэтому конпелятор НЕ ВЕКТОРИЗУЕТ флоат по умолчанию, ну никак. Даже такую банальщину.

Для решения этих проблем - есть ключик -funsafe-math-optimizations, который входит в -ffast-math, который кладёт на точность при вычислениях. Добавив его мы получаем уже 44.9GB/s.

Но теперь мы получаем ещё одну проблему - надо думать: «как бэ сунуть эту ключик не повредив там, где этот ключик не нужен».

Поэтому ноцанам, которые хотят быстро и не хоятт рандомных жоп из-за тупости конпелятора - пишут всё руками. Допустим на той же сишке это пишется так:

double memadd_autovec(buf_t buf) { //5.609465GB/s, либо 44.969652GB/s с ffast-math
  float * it = buf_begin(buf), * end = buf_end(buf), summ = 0.;
  do {
    summ += *it++;
  } while(it != end);
  return summ;
}

double hsumf(__v8sf v) {
  return (v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6] + v[7]);
}

double memadd_vec(buf_t buf) { //45.652002GB/s и класть на ffast-math
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ += *it++;
  } while(it != end);
  return hsumf(summ);
}

Т.е. разницы никакой нет, кроме нужной нам реализации горизантального сложение вектора. Когда я говорил пацану: «векторную сишку для написания быстрого кода юзать намного проще, чем плюсы» - поцан нипонимэ, да и любые пацаны скажут - ну дак с -ffast-math оба выдают по 45гигов - нахрен эта сишка нужна?

А вот зачем:

double memadd(buf_t buf) { //132.878440GB/s
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
  } while(it != end);
  return hsumf(summ);
}

Это называется пацанский анролл копипастой, а вот заставить конпелятор нормально что-то разанролить очень сложно.

Если бы мы слушали всяких «гуру», которые нам вещают: «анрол говно и не нужен» - мы бы так и седели с 45-ю гигами, а так мы сидим с 132.878440GB/s. Т.е. анролл нам дал немного не мало ~300%.

Но основная мысль, которую толкают всякие «гуру» - это не надо следить за тактами/считать такты и прочее. Но мы о5 сделаем наоборот и посмотрим что будет.

Т.к. наш юзкейс упирается на 99% в throughput и дёргается одна инструкция, то нам достаточно просто считать теоретическую производительность для моего камня. 4.5(частота камня)*8(т.е. у нас камень с avx, то там вектор 32байта, либо 8флоатов.)*1(throughput нашей инструкции - в данном случае vpaddps из интел мануала). Т.е. 36гигафлопс, либо ~144гига. Т.е. мы сняли овер 90% теоретической производительности - остальные 10% у нас ушли в наши циклы, всякие горизонтальные суммы вектора и прочее, ну и конечно же чтение данных из кеша.

Но самое смешное - на моём хасвеле умножение имеет throughput 0.5 - т.е. на хасвеле умножение быстрее сложения. Это новая забористая трава у интела.

Казалось бы - какой жопой сложнее оказалось медленнее умножения - а вот так, на всяких штеудах производительность уже давно зависит не от каких-то технических возможностей, а от маркетинга и хотелок.

Поэтому очень смешно слушать, когда какие-то пацаны говорят: «float point имеет такую же производительность как и инты» - нет, оно имеет такоу же производительность лишь по причине того, что на штеуде инты тормазят так же, как и float.

И чтобы окончательно в этом убедится - мы взглянем на fma(вариации умножения со сложением/вычитанем), которые имеют throughput 0.5 - да, да - на хасвеле умножение+сложение в 2раза быстрее просто сложения. Это уже не просто трава - это что-то принципиально новое.

У целочисленного сложения же throughput 0.5 и казалось бы, если мы поменяем в нашей функции float на int - у нас будет сложение работать в 2раза быстрее, но это не так. Оно выдаёт те же 130гигов, а почему?

Вообще у камня есть такая фича, допустим у нас:

add $1, %reg0//вот тут инструкция add залочит регистр reg0
add $1, %reg0//а эта инструкция уйдёт в лок до особождения предыдущей инструкцией регистра reg0

Чтобы такой жопы небыло - есть специальная фича:

add $1, %reg0//lock reg0
add $1, %reg0//И тут вместо того, чтобы уйти в лок - камень вместо reg0 даёт инструкции любой свободный регистр.

Эта фича называется прееименование регистров, либо как-то так - мне лень гуглить.

Дак вот штука в том, что фича работает через жопу. Мне лень читать мануал и искать почему так, но штука в том, что она ограничивает throughput. На умножении и целочисленном сложении она огранивает throughput c 0.5 до 1.

И вот я решил заюзать сложении через fma:

__v8sf fmaadd(__v8sf a, __v8sf b) {
  return _mm256_fmadd_ps(_mm256_set1_ps(1.), a, b);// a + b * 1. == a + b.
}

double memadd_fma(buf_t buf) {
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ = fmaadd(summ, *it++);
  } while(it != end);
  return hsumf(summ);
}

Но меня ждала жопа: 27.347290GB/s, причем не анролл и ничего не помогал. Я уж подумал, что мануал наврал, но позже до меня допёрло: у неё latency 5тактов и ((4.5×8)÷5)×4 ~= 29гигов - т.е. я получаю производительность с её latency, но какой жопой оно так?

Потом я вспомнил, что гцц гинерит анрольный код вида:

add $1, %reg0
add $1, %reg0
//а не
add $1, %reg0
add $1, %reg1

Т.е. на неё вообще не работает переименовывание регистров - и инструкции постоянно в локе. Я это проверил и оказался прав. Ну и я написал такой мемадд:


__v8sf fmaadd(__v8sf a, __v8sf b) {
  return _mm256_fmadd_ps(_mm256_set1_ps(1.), a, b);
}

inline void fma_10way_finality(__v8sf * cache, __v8sf * it, __v8sf * end) {
  switch(end - it) {
    case 8:
      *(cache + 7) = fmaadd(*(cache + 7), *(it + 7));
      *(cache + 6) = fmaadd(*(cache + 6), *(it + 6));
    case 6:
      *(cache + 5) = fmaadd(*(cache + 5), *(it + 5));
      *(cache + 4) = fmaadd(*(cache + 4), *(it + 4));
    case 4:
      *(cache + 3) = fmaadd(*(cache + 3), *(it + 3));
      *(cache + 2) = fmaadd(*(cache + 2), *(it + 2));
    case 2:
      *(cache + 1) = fmaadd(*(cache + 1), *(it + 1));
      *(cache + 0) = fmaadd(*(cache + 0), *(it + 0));
    case 0:
      break;
    default: error_at_line(-1, 0, __FILE__, __LINE__, "bad_aligned");
  }
}

double memaddfma_10way(buf_t buf) {
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = (__v8sf){};
  __v8sf * cache = (__v8sf[10]){{}};
  uint64_t i = 0;
  while((it += 10) <= end) {
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    i = 0;
  }
  fma_10way_finality(cache, (it - 10), end);
  summ = (*(cache + 0) + *(cache + 1) + *(cache + 2) + *(cache + 3) +
	  *(cache + 4) + *(cache + 5) + *(cache + 6) + *(cache + 7) +
	  *(cache + 8) + *(cache + 9));
  return hsumf(summ);
}

Пришлось хреначить финалити, ибо тут «анролл» на 10, а почему на 10 - для максимального throughput"а - надо, чтобы каждый каждый регистр юзался через 5тактов - т.е. 10регистров.

И вся эта порятнка нужна для борьбы с тупостью конпелятора.

Это уже: 214.167252GB/s(раельно там в районе 250 - просто мой бенч говно). 107 гигафлопс на ведро. Из теоретических 144, но тут уже влияние кеша. Причем 50+ из которых выкидываются и просто бесплатные.

Теперь вопрос к пацанам - что нам дадут эти гагфлопсы, когда у нас будет массив не 32килобайта, а 32мегабайта? Зачем нужно выживать максимум, когда скорость памяти отсилы 20-30гигабайт и нам хватит даже С++ кода с ffast-math?

Ну и призываются упомянутые мною пацаны: mv - этот тот експерт, что вещал про «руками переименовывать регистры не надо» и «анрол ваще ненужен», emulek вещал про ненужность счёта тактов, и не понимал что такое «беслпатно», AIv - не понимал в чем проблема плюсов, ck114 - так же не понимал в чем проблема плюсов.

Бенчи: https://gist.github.com/superhackkiller1997/606be26fa158ef75501d - вроде я там ничего не напутал.

P.S. - не выпиливайте пж, пусть пацаны «нужно» или «не нужно». Мне интеерсно. Ну и там рекомендации пацанов.



Последнее исправление: beastie (всего исправлений: 1)

Ответ на: комментарий от Carb_blog

Изначально это вообще был мемадд - складывание 2-х массивов, но я посчитал это слишком сложным для эмулеков, ибо там надо пилить в вариации кеш/рама.

Ну так перестань спорить и давай его сюда! :)

yyk ★★★★★
()
Ответ на: комментарий от Kakadu

Можете как-нибудь ещё раз подытожить для медленно соображающих?

А что тут итожить - используйте интринсики, да не забывайте про анролл, вот и весь сказ.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от emulek

Если у тебя есть числа 1,2,100,200,10000,20000, то складывать их надо так

(1.0 + 2.0 + 100.0 + 200.0 + 10000.0 + 20000.0) абсолютно != (1.0 + 2.0) + (100.0 + 200.0) + (10000.0 + 20000.0)

?

quest ★★★★
()
Ответ на: комментарий от quest

Вазелин, перчатки есть?

Зачем?

(1.0 + 2.0 + 100.0 + 200.0 + 10000.0 + 20000.0) абсолютно != (1.0 + 2.0) + (100.0 + 200.0) + (10000.0 + 20000.0) ?

>>> 10e-8 + 10e-8 + 2e9
2000000000.0000002
>>> 10e-8 + 2e9 + 10e-8
2000000000.0
>>> 
tailgunner ★★★★★
()
Ответ на: комментарий от Kakadu

Правильно ли я понял, что CPU сам понимает, что надо регистры переименовать, т.е. без помощи компилятора?

Ну типа того - я сомневаюсь, что он понимает - там скорее какая-то хитрая индексация вместо реальных имён регистров.

P.S. Я так понимаю, что Вы доказали, что можно (обмазавшись интринсками) руками написать более эффективный код, чем генерит компилятор?

Тут нет интринсиков(только фма), тут вообще-то векторная гнусишка.

Нет, суть в том, что для этого рук не надо - это пишется так же просто, как и обычный код. Всеж любят кукарекать, типа сложно - конпелятор умеет сам и выжать можно лишь 1-2% и то сидя 10суток карпя на ассемблере и тысячи строк кода вместо одной.

Это первый посыл.

Второй посыл - это не слушать експертов, вот с тем же переименованием - тот же «експерт» mv мне доказывал, что «х86 умеет сам переименовывать регистры - 100% имеет, а твоё ручное только регресс даёт, поэтому руками не надо» - я же доказывал обратное.

Сейчас я привел пример, где самый современный х86 нихрена не может периименовывать регистры либо вообще, либо с потерей 50% производительности.

Это вроде как известный факт.

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

Суть - показать, что это не так - это мифы.

P.P.S. Не обижайтесь, но орфографические ошибки вызывают некоторые сложности с восприниманием текста. Было бы круто, если можно с этим что-нибудь сделать.

Мне лень ставить спеллчекер, да и там скорее искажения специальные, либо пункация/семантика - вялая постройка предложения, либо я пропускаю буквы, ибо клава мембранное говно.

Carb_blog
() автор топика
Ответ на: комментарий от no-such-file

Но на твоём примере не работают другие случаи.

Работает в твоём понимании - это просто даёт результат, которым можно подтерется, в аналогии эмулека. Суть в том, что его складывалка - такой же частный случай, которая выдаёт такое же гвоно, как и моя.

10113.577148//моё
10113.572864//умножение

Ты там упарывался и доказывал, что вычисления на пуле коротких массивов (типа такой список, но «анроллнутый») быстрее, чем на просто монолитном массиве.

Упоролсячтоли? Он спрашивал «как бы заюзать быстрый вектор, чтобы не тормазил на реалоке и не „жрал память“» - я ответил - юзай malloc(1000500000);

Вы там начали кукарекать про то, что malloc(1000500000) не круто и прочее.

Ты начал нести какую-то херню про локальность - я спросил - нахрен она нужна, локально больше страницы смысла почти не имеет. Ты начал нести какую-то херню про каких-то пацанов, мануалы и прочее.

Я тебе предлогал тест - возми пулл страниц и записывай данные через одну - она будет работать так же.

Нехрен мне тут рассказывать - у меня идеальная память, я максимум ники/имена/названия могу не вспомнить сразу.

И да, ты что мне отвечаешь - я спорил с каким-то студентом, который говорил про в1000раз сливаю х86 на фпга. Почему-то я думаю, что это был ты. Это был ты?

Carb_blog
() автор топика

Теперь я знаю, что бывает с аутистами в переходном возрасте.

anonymous
()
Ответ на: комментарий от Carb_blog

Просуммируй 1.234567 32к раз.

10113.577148//моё
10113.572864//умножение

Ну ты чё, даже умножить не в состоянии? 1.234567*32000=39506.144000, а 1.234567*(32*1024)=40454.291456. Даже близко не лежит, что ты там суммировал то? И да, покаж полный пример кода.

no-such-file ★★★★★
()
Ответ на: комментарий от bhfq

Кстати да, альтернативное название – байтоёб под кокосом.

anonymous
()
Ответ на: комментарий от Carb_blog

Почему-то я думаю, что это был ты. Это был ты?

Странный вопрос при такой идеальной памяти, и нет, это был не я.

локально больше страницы смысла почти не имеет

Вот. А я утверждаю, что имеет.

Я тебе предлогал тест - возми пулл страниц и записывай данные через одну - она будет работать так же.

Вот ты и возьми, и запили своё сложение по пулу страниц, а не по массиву. Будет работать также?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

запили своё сложение по пулу страниц, а не по массиву.

Чем «пул страниц» отличается от mmap анонимной памяти (с MAP_POPULATE)?

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от no-such-file
40454.292969
40454.291456

В килобайтах хреначь, а не в числах. Да какая разница сколько - оно будет давать правильный результат. Тут плывёт флоат.

Carb_blog
() автор топика
Ответ на: комментарий от tailgunner

В пуле страницы идут не подряд, а как попало. Для линейного доступа нужно транслировать индекс «массива» в адрес конкретного пула+смещение в пуле. И это, утверждается, что ни разу не медленнее, чем простой, дубовый массив.

no-such-file ★★★★★
()
Ответ на: комментарий от Carb_blog

Сейчас я привел пример, где самый современный х86 нихрена не может периименовывать регистры либо вообще, либо с потерей 50% производительности.

А что предлагаешь делать с различиями процессоров внутри множества x86? У тех же AMD свои особенности, у Intel свои, у VIA свои. Я уже не говорю о разных микроархитектурах разных поколений.

Ну и если хочешь сделать что-то годное, запили drop-in либу с ускоренными вариантами стандартных функций (как не так давно народ разные либы для работы с памятью гонял: tcmalloc, jemalloc, etc).

devl547 ★★★★★
()
Ответ на: комментарий от Carb_blog

Да какая разница сколько - оно будет давать правильный результат. Тут плывёт флоат.

Ну, эта, давай не для степени двойки. 32000 или 8000. И дал бы уже полный код, я б сам посмотрел что получается.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

В пуле страницы идут не подряд, а как попало.

«Как попало» по виртуальному адресу или по физическому? Если по физическому, то это не имеет значения с MAP_POPULATE; если по виртуальному, то нам придется вручную делать переходы между страницами - понятно, что из-за этого мы что-то потеряем.

Для линейного доступа нужно транслировать индекс «массива» в адрес конкретного пула+смещение в пуле

Еще раз: виртуальные адреса пула непрерывны и линейны?

tailgunner ★★★★★
()
Ответ на: комментарий от devl547

Ну и если хочешь сделать что-то годное, запили drop-in либу с ускоренными вариантами стандартных функций

Да хотя бы сравнить производительность с liboil: http://liboil.freedesktop.org/documentation/liboil-liboilfuncs-math.html

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 2)
Ответ на: комментарий от Carb_blog

Да какая разница сколько - оно будет давать правильный результат. Тут плывёт флоат.

Есть разница. Кстати, я сейчас допёр, ты же считаешь сумму частями по 8 флоатов - этим спасаешься, в данном конкретном примере.

Надо таки считать по рандомным числам, как емулек предлагал.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от tailgunner

ИМХО, liboil довольно неудачный пример. Насколько я понимаю, это просто набор оптимизированных функций для мультимедии.

Как всякие Yeppp!, ACML, MKL относительно обычной libm.

Их нельзя тупо через ld_preload подгрузить и протестировать изменение скорости.

devl547 ★★★★★
()
Последнее исправление: devl547 (всего исправлений: 2)
Ответ на: комментарий от devl547

У тебя ссылка не работает.

Работает :)

Да и liboil довольно неудачный пример

Смотря что считать удачностью. Простые функции, готовая либа.

Их нельзя тупо через ld_preload подгрузить и протестировать изменение скорости.

Чрезе LD_PRELOAD? Это бессмысленно. Сабжевая техника оптимизации - для узких мест, которые в готовых программах уже худо-бедно оптимизированы.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 2)
Ответ на: комментарий от tailgunner

Потери на расчете переходов очевидны.

Не так очевидны, в той теме в вектор докидывали данные. Что быстрее: медленная реалокация вектора с последующим быстрым расчётом, или быстрое докидывание в deque с последующим медленным расчётом? Я был за то, что первый вариант в большинстве случаев быстрее, т.к. в основном время жрут расчёты. А если расчётов так мало, что есть преимущество deque, то время работы и так будет маленькое и можно не заморачиваться.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Что быстрее: медленная реалокация вектора с последующим быстрым расчётом, или быстрое докидывание в deque с последующим медленным расчётом?

Эта задача не имеет отношения к сабжу.

tailgunner ★★★★★
()
Ответ на: комментарий от no-such-file

Странный вопрос при такой идеальной памяти, и нет, это был не я.

Патамучто я не помню как вас там всех зовут.

Вот. А я утверждаю, что имеет.

double memadd4096(buf_t buf) {
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128*4 512
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;//32*4 128
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
    it += 128;
  } while(it != end);
  return hsumf(summ);
}

21ГБ/с нормально
20.5ГБ/с через страницу

Там можно ещё поиграться, но результат понятен.

Вот ты и возьми, и запили своё сложение по пулу страниц, а не по массиву. Будет работать также?

Да.

Carb_blog
() автор топика
Ответ на: комментарий от tailgunner

Он просто ракал, который переиначивает мои слова.

Пулл страниц - это

void * get(void) {
  static base = bla-bla;
  void * ret = base;
  base += 4096;
  return ret;
}

Вот мы вместо одного гет, как в массиве - делаем гет через 1 и пишем 10101010.

Carb_blog
() автор топика
Ответ на: комментарий от devl547

А что предлагаешь делать с различиями процессоров внутри множества x86?

Дак не пологатся на х86 - пусть конпелятор переименовывет регистры руками, вернее конпелятором и не надеятся на х86, и не слушать тех бомжей, что говорят обратное.

Это работает для всех х86.

У тех же AMD свои особенности, у Intel свои, у VIA свои.

Нет. Читать проще, чем догадываться.

Я уже не говорю о разных микроархитектурах разных поколений.

Всё везде тоже самое.

Ну и если хочешь сделать что-то годное, запили drop-in либу с ускоренными вариантами стандартных функций (как не так давно народ разные либы для работы с памятью гонял: tcmalloc, jemalloc, etc).

Это нужно для нулёвых бомжей, а норм пацанам это не нужно - тебе это сделают жабисты, либо интел за еду.

Мне проще запилить, чем заюзать говнолибу.

Carb_blog
() автор топика
Ответ на: комментарий от Carb_blog

Всё везде тоже самое.

Расскажи мне еще раз, как у AMD Stars, Jaguar и Kaveri всё то же самое. Техдокументацию чтоль почитай.

Мне проще запилить

Запили. Во все 100500 софтин.

devl547 ★★★★★
()
Ответ на: комментарий от tailgunner

Кусок фекалии, в лучшем случае это будет так же. Ещё раз - этот код выдаёт 132гига(обычный адд).

У меня частота каменья 4.5ггц, длинна вектора 8флоатов(32байта), а throughput у обычного add 1. - т.е. ((4.5 * 10^9 * 32)/1)/2^30 = 134,110450745GB/s. 98.5% от максимальной теоретической производительности. Больше выжать просто не реально, ибо эти 1.5% занимает оверхед на цикл и бенч.

Нахрен мне сравнивать? Максимум оно будет так же.

Carb_blog
() автор топика
Ответ на: комментарий от tailgunner

Он сказал «как попало», т.е. в случайном порядке, а ты делаешь через 1.

А мне какого хрена я буду слушать, что мне курлычит палумный идиот, какой жопой в случйаном порядке? Как вы меня одалели, как можно быть настолько тупыми?

А чёж он массив не читает в случайном порядке?

У тебя же 5звёзд - ты же можешь читать удалённые месаги? Вот перечитай наш спор. Если можешь - я тебе его даже найду.

Carb_blog
() автор топика
Ответ на: комментарий от Carb_blog

Кусок фекалии, в лучшем случае это будет так же

В лучшем случае это будет немного хуже.

Нахрен мне сравнивать?

А нахрен ты вообще сюда пришел?

А мне какого хрена я буду слушать, что мне курлычит палумный идиот

Он сказал это мне. И нет, ты не обязан его слушать (да и вообще никого слушать не обязан).

Производительность; илитный запил оптимальных реализаций и основы матчасти. (комментарий)

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от devl547

Расскажи мне еще раз, как у AMD Stars, Jaguar и Kaveri всё то же самое. Техдокументацию чтоль почитай.

И что я тебе должен рассказать? Чем твоё бесполезное говно не х86? Такой же х86, добавили сопроцессор на кристалл? Гениально, какой жопой он относится к х86?

Это говно хоть считать умеет, либо работает через какой-то обоссанный биндинг к шейдерному говну? Скорее всего так, дак кому это говнище нужно? У меня такая же байда на камне есть, новшество?

Если они запилил прямую считалку с емуляцей говношейдеров, то возможно это что-то вменяемое и новое, но никакой жопой к х86 не относится.

Запили. Во все 100500 софтин.

Каких таких софтин? И нахрен мне их запиливать - то, что мне надо - я запилю.

Carb_blog
() автор топика
Ответ на: комментарий от Carb_blog

какой жопой в случйаном порядке?

Ну так ты же предлагал динамически навыделять страниц. Где будут выделены эти страницы в общем случае не предсказуемо.

no-such-file ★★★★★
()
Ответ на: комментарий от tailgunner

В лучшем случае это будет немного хуже.

Что это? Что лучше? Нахрен ты рассуждаешь, если нихренан е понимаешь?

А нахрен ты вообще сюда пришел?

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

Я тебе объяснил, что оно быстрее быть физически не может - ты даже чистую синтеттику хрен быстрее сделаешь. Ты не хочешь слушать? Это мои проблемы?

Ты мне можешь назвать хоть одну причину по которой оно может каким-то образом «быстрее» работать, у тебя же должны быть предпосылки, а?

Он сказал это мне. И нет, ты не обязан его слушать (да и вообще никого слушать не обязан).

Если он сказал тебе, то какого хрена ты мне говоришь, что У МЕНЯ ТАМ БЫТЬ ДОЛЖНО? а? Сказал тебе - мне не интересно.

Carb_blog
() автор топика
Ответ на: комментарий от Carb_blog

Нахрен ты рассуждаешь, если нихренан е понимаешь?
Ты мне можешь назвать хоть одну причину по которой оно может каким-то образом «быстрее» работать
Если он сказал тебе, то какого хрена ты мне говоришь, что У МЕНЯ ТАМ БЫТЬ ДОЛЖНО? а?

Да мне показалось, что у тебя ремиссия. Вполне очевидно, что я ошибся.

tailgunner ★★★★★
()
Ответ на: комментарий от no-such-file

Какие страницы? Кого выделять? Кого предлагал? Иди ради интереса перечитай - что я думаю о «динамическом» и «рандомном» - это описывается мою крайне красочно в каждой теме, где я отписывался.

Какая нахрен непредсказуемость, чего навыделять - хреначь malloc(10005000) - пиши в любую, ничего не поменяется.

И иди погугли что такое pagefault, и почему рандомность не бенчится и не имеет смысла.

Ещё раз тебе повторю - локальность на уровне большей страницы не имеет смысла. Если ты не будешь «полностью» заполнять страницы - ты будешь дёргать их чаше, а попадать в dtlb реже. Это единственное, что ты можешь запартачить.

А с какими адресами связаны страницы - покласть, хоть через 1, хоть через 100. Ты только тратишь vmem - всё.

Но это уже проблема твоих рук, а не локальности.

Carb_blog
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.