LINUX.ORG.RU
ФорумTalks

Раздобыл кросскомпилятор под эльбрус

 , ,


1

4

Захотелось что нибудь несложное покомпилировать.

Например хэловорд на си: https://pastebin.com/KFNHABjm (генератор цветового uid из строк)

Компилировал с такими опциями:
g++ -S -O2 -march=x86-64 -std=c++11 test.cpp

l++ -S -O3 -mcpu=elbrus-v3 -std=c++11 test.cpp

$ g++ --version
# g++ (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609

$ l++ --version
# lcc:1.20.17:Mar-3-2016:e2k-generic-linux.cross:i386-linux
# gcc (GCC) 4.4.0 compatible
Согласно докам, -O3 на lcc это не агрессивные оптимизации примерно соответствующие О2, elbrus-v3 это архитектура от Эльбрус-4C и выше, 64бит задействовано по умолчанию.

Для интела получился слишком большой выхлоп 900kb 32k строк (выкладывать безсмысленно)

Для второго 250kb 9k строк (почему такая разница? инклюды не входят?)
собственно выхлоп: https://pastebin.com/WC2CuZ5k есть довольно любопытные участки и операции

Одна условная запись и непонятная магия с регистрами/предикатами и все в одной инструкции, после которой вставлена пустая инструкция (пропуск такта?)
	{
	  ct	%ctpr3 ? ~%pred0
	  std,2	%dg13, %dr12, %dr11 ? %pred0
	  pass	%pred0, @p0
	  pass	%pred1, @p1
	  landp	@p0, ~@p1, @p4
	  pass	@p4, %pred2
	  landp	@p0, @p1, @p5
	  pass	@p5, %pred1
	}
	{
	}


пут-тег, слияние, istofd (int-single to float-double ?), sxt/scls (???)
$_ZNSs12_S_constructIN9__gnu_cxx17__normal_iteratorIPKcSsEEEEPcT_S6_RKSaIcESt20forward_iterator_tag:
	{
	  setwd	wsz = 0x13, nfx = 0x1
	  setbn	rsz = 0x3, rbs = 0xf, rcur = 0x0
	  disp	%ctpr1, $.L4337; ipd 2
	  getsp,0	_f32s,_lts1 0xfffff960, %dr5
	  addd,1	0x0, [ _f64,_lts2 $_GLOBAL_OFFSET_TABLE_@ABS ], %dr3
	  puttagd,2	%dr0, 0x0, %dr17
	  adds,3,sm	0x0, 0x0, %r21
	  addd,4,sm	0x0, 0x0, %dr20
	  puttagd,5	%dr1, 0x0, %dr16
	}
...
	{
	  merges,0	%g16, %g21, %g16, %pred0
	}
...
	{
	  setwd	wsz = 0x20, nfx = 0x1
	  setbn	rsz = 0x3, rbs = 0x15, rcur = 0x0
	  disp	%ctpr1, $.L2085; ipd 2
	  addd,0	0x0, _f64,_lts1 0x20ff2000000000, %dg16
	  sxt,1	0x6, %r5, %dg17
	  scls,2	0x9, 0x9, %r1
	}
...
	{
	  call	%ctpr3, wbs = 0x1c ? %pred0
	  istofd,0,sm	%r1, %dr1
	}
	


Ну и какой то тяжелый цикл с долгими одиночными инструкциями (fdtoidtr - 6 тактов, fmuld - 4 такта, итд. Если я правильно понял как это читать)
$.L1779:
	{
	  loop_mode
	  nop 3
	  faddd,1,sm	%dr1, %db[2], %db[0]
	}
	{
	  loop_mode
	  nop 3
	  fmuld,1,sm	%dr7, %db[0], %db[0]
	}
	{
	  loop_mode
	  nop 5
	  fdtoidtr,1,sm	%db[0], %db[1]
	}
	{
	  loop_mode
	  sxt,2,sm	0x6, %b[1], %db[1]
	}
	{
	  loop_mode
	  nop 3
	  idtofd,1,sm	%db[1], %db[1]
	}
	{
	  loop_mode
	  nop 3
	  fsubd,1,sm	%db[0], %db[1], %db[0]
	}
	{
	  loop_mode
	  nop 3
	  fmuld,1,sm	%db[0], %db[1], %db[0]
	}
	{
	  loop_mode
	  nop 5
	  fdtoidtr,1,sm	%db[0], %db[1]
	}
	{
	  loop_mode
	  sxt,2,sm	0x6, %b[1], %db[1]
	}
	{
	  loop_mode
	  nop 3
	  idtofd,1,sm	%db[1], %db[1]
	}
	{
	  loop_mode
	  nop 3
	  fsubd,1,sm	%db[0], %db[1], %db[0]
	}
	{
	  loop_mode
	  nop 2
	  fmuld,1,sm	%db[0], %dr5, %db[0]
	  ldb,2,sm	%dr6, %dr2, %b[3]
	  addd,5,sm	%dr2, 0x1, %dr2
	}
	{
	  loop_mode
	  getfs,2,sm	%b[3], %r4, %b[2]
	}
	{
	  loop_mode
	  nop 2
	  istofd,0,sm	%b[2], %db[0]
	  faddd,1,sm	%db[1], %db[0], %dr1 ? %pcnt0
	}
	{
	  loop_mode
	  alc	alcf=1, alct=1
	  abn	abnf=1, abnt=1
	  ct	%ctpr1 ? %NOT_LOOP_END
	}
Компилятор взял осюда вполне легально (привет тарищу-майору).
Устанавливаентся вытряхиванием архива в /opt/mcst/ и симлинканьем lcc и l++ куда нибудь в /usr/local/bin

★★★

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

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

ну сама широкая команда (скобками разделена) такт занимает, а в ней еще написано «ждать 3 такта» итого - 4.
Я вот только не понял в это время процессор другие инструкции исполнять может или нет. Ведь если компилятор заранее нопы просчитал, значит он в принципе может понять что вот это устройство три такта использовать нельзя значит следующие три инструкции его использовать не будут, вопрос только железо обучено такому или нет.

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

А, я на nop не обратил внимание. Но по такому предположению выглядит странно, что даже faddd/fsubd там 3+ такта жрут. Или это как-то связано с loop_mode

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

Ну так и операции то над 64 битными числами же (все равно много?)
Причем одна такая инструкция за эти такты может умножать/складывать как одно 64 битное число так и два 32 битных (? 4x16 (? 8x8 )) и таких мини-SIMDов в одной ШК может быть до четырех. В поздних процессорах - до 6и и регистры там уже 128 битные, но наверняка это все то же не бесплатно.

Или это как-то связано с loop_mode

Да нет в других местах задержки те же: ... может быть связано с -mcpu=elbrus-v3 (Эльбрус-4С 65нм)
Надо бы компильнуть под 28нм 8С/8СВ и посмотреть что там будет.

faddd/fsubd


А, так падажжи ёбана, да - только в накрученом цикле столько почему то

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

Ну так и операции то над 64 битными числами же (все равно много?)

FPU на первопне работал с 80-битными регистрами и мог делать fmul за один такт. Целочисленный блок работал параллельно и мог исполнять до двух инструкций за так.
А уж сколько с тех пор всяких SIMD завезли - не счесть.

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

FPU на первопне работал с 80-битными регистрами и мог делать fmul за один такт.

Почему тут написано 7/8?
Я конечно дофига всего еще не знаю, но у всех процессоров по части математики +/- одно и то же.
То есть, ну вот как у тебя может быть вещественное умножение за один такт если там банально действий >1 ? Квантавые какие то вычисления что-ли.

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

Почему тут написано 7/8?

Не знаю, для какого это проца.
FPU у первопня был конвейерный, следующая независимая инструкция могла начать исполняться не дожидаясь предыдущей. ЕМНИП, фактически результат fmul был доступен через 3 такта. Плюс, многие fpu-интсрукции могли непосредственно спариваться с fxchg. Но точно подробностей сейчас не помню, нужно гуглить.

Я конечно дофига всего еще не знаю, но у всех процессоров по части математики +/- одно и то же.

ФПУ у пня драматически превосходил 486 или амд-шные к5/к6/к7

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

FPU у первопня был конвейерный, следующая независимая инструкция могла начать исполняться не дожидаясь предыдущей. ЕМНИП, фактически результат fmul был доступен через 3 такта.

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

ФПУ у пня драматически превосходил 486 или амд-шные к5/к6/к7

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

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

madcore Так, посоны, спокуха, ща я всё поясню.

ну сама широкая команда (скобками разделена) такт занимает, а в ней еще написано «ждать 3 такта» итого - 4.

Да.

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

Инструкции исполнять может, устройство эти 3 такта использоваться тоже может. Задержка - это время до готовности результата. Т.е. для любой инструкции мы 1-ым тактом отсылаем инструкцию на первую стадию конвейера, и после этого на следующем такте можем задействовать тоже устройство. Но вот результат в нужном регистре надо ждать долго.

А, я на nop не обратил внимание. Но по такому предположению выглядит странно, что даже faddd/fsubd там 3+ такта жрут. Или это как-то связано с loop_mode

Никак не связано, для плавающих операций 4 такта задержки - это норма.

А, так падажжи ёбана, да - только в накрученом цикле столько почему то

В ненакрученных там точно такая же задержка выставляется.

FPU у первопня был конвейерный, следующая независимая инструкция могла начать исполняться не дожидаясь предыдущей. ЕМНИП, фактически результат fmul был доступен через 3 такта.

На Эльбрусе (думаю, как и на всех современных камнях) также (только 4 такта)

На скольок я понимаю, вопрос вызвала плохо набитая ШК (Широкая Команда). Если посмотреть на цикл, то можно заметить что мы имеем рекуррентную зависимость между переменной b и mask. Т.е. мы в начале итерации считаем b, и не можем запускать следующую итерацию до тех пор пока не посчитаем в конце данной mask. Т.к. кроме данных вычислений в цикле ничего не происходит, ШК забиватеся слабо.

alexanius ★★
()
9 декабря 2018 г.
Ответ на: комментарий от alexanius

смотри: мы тут настраивали CI для сборок под Эльбрус, так вот полное выпадание всего мцст из современной экосистемы очень расстраивает.

Что бы собрать под арм достаточно: apt install crossbuild-essential-armhf

А вот под Эльбрус — надо пообщаться с поддержкой, какие-то doc файлы прочитать (вместо онлайн документации), какие-то пакеты распаковать и там уже что-то значит сделать.

Конечно мы себе всё упаковали в бинари и выложили туда, откуда CI может стянуть.

Но было бы лучше, если бы это делали вы, причем не нужен тут никакой уникальный способ, надо просто сделать всё стандартно как у всех.

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