Pull to refresh
3
Karma
0
Rating
  • Followers
  • Following 1

Вычисляем на видеокартах. Технология OpenCL. Часть 1a. Как работает OpenCL

В общем-то opencl ± жив. И SPIR-V в нём тоже поддерживается.

OMF еще послужит

Это очень похоже на модули из C++20

OMF еще послужит

Очевидно, никакие

Зачем нужен регистр SPL

Более того, архитектура x86 явно запрещает переупорядочивать операции чтения. То есть нельзя поменять местами два чтения или две записи. Можно только чтение и запись.

Зачем нужен регистр SPL

Всё-таки ABI, а не API

Зачем нужен регистр SPL

По стандарту C++, например, во всех операциях переменные целочисленных типов, меньшьх int, должны быть преобразованы к int. Так сложилось, что в x86-64 тип int 32-битный. Поэтому вся целочисленная арифметика как минимум 32-битная.

GCC и LLVM так же генерируют 32-битные операции для bool-переменных: https://godbolt.org/z/1vqnjWezs

Зачем нужен регистр SPL

Они и не нужны. На самом деле компиляторы практически не используют их.

Зачем нужен регистр SPL

Первые шесть: RSI, RDI, RDX, RCX, R8 и R9. Подробнее здесь: https://uclibc.org/docs/psABI-x86_64.pdf

Зачем нужен регистр SPL

Зачем вообще нужны эти R8-R15? Это что, RISC-процессор?

Когда доступно много регистров, компилятору становится проще жить. Не надо без конца спиливать переменные в память. Плюс, с добавлением дополнительных регистров пришло новое соглашение о передаче параметров в функции: первые 6 параметров передаются на регистрах.

Зачем нужен регистр SPL

Ну, мне иногда интересно потыкать палочкой в разные компиляторы и посмотреть, какой код они генерируют. Не то, чтобы в данном случае был какой-то практический смысл. В конце концов, если бы PL/I был кому-то нужен, компиляторы для него писали бы разработчики процессоров (-:

Зачем нужен регистр SPL

Ну, судя по сайту автора, это компилятор PL/I. Только там нет исходников, а у меня нет винды, поэтому я не могу запустить бинарную сборку.

Зачем нужен регистр SPL

Так, эта, компилятор — он таки есть или его таки нет?

Компилятор, вероятно, есть. Но Optimization Reference Manual от Intel и AMD читать, похоже, умеют не все (-:

Зачем нужен регистр SPL

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

Зачем нужен регистр SPL

В том-то и дело, что для железа выгоднее, когда код вообще не использует 8- и 16-битную арифметику

Зачем нужен регистр SPL

На современных процессорах x86 использование 8- и 16-битных регистров бьёт по производительности. В частности из-за того, что называется source merge. Собственно, все регистры общего назначения 64-битные. 32-битные инструкции обнуляют старшую часть регистра, а 8- и 16-битные её сохраняют --- очевидно это достигается исполнением дополнительных микроинструкций.

В общем-то, эти регистры сохранены для совместимости со старым софтом, и лучше бы их совсем не использовать. Собственно, разработчики мэйнстрим-компиляторов и не используют этих регистров, а всюду, где возможно, расширяют 8- и 16-битную арифметику до 32 бит.

Как увеличить стек FPU

FMA, конечно, точнее. Только при -ffast-math компилятор может делать некоторые другие нехорошие вещи. Например, изменять порядок суммирования, если складывается несколько чисел. Также компилятор может в этом режиме включить denormals flush to zero. А это всё не очень хорошо влияет на точность.

Как увеличить стек FPU

Сейчас ещё проверил: если подать -ffast-math, компилятор начинает генерировать FMA, но ну его к чёрту. Нельзя включать -ffast-math, если есть требования к точности:

.LBB12_3:
	vmovsd	xmm1, qword ptr [rip + .LCPI12_1] # xmm1 = mem[0],zero
	vfmadd213sd	xmm1, xmm0, qword ptr [rip + .LCPI12_794] # xmm1 = (xmm0 * xmm1) + mem
	vmovsd	xmm0, qword ptr [rip + .LCPI12_795] # xmm0 = mem[0],zero
	vfmadd213sd	xmm0, xmm1, qword ptr [rip + .LCPI12_796] # xmm0 = (xmm1 * xmm0) + mem
	vfmadd213sd	xmm0, xmm1, qword ptr [rip + .LCPI12_797] # xmm0 = (xmm1 * xmm0) + mem
	vfmadd213sd	xmm0, xmm1, qword ptr [rip + .LCPI12_798] # xmm0 = (xmm1 * xmm0) + mem
	vfmadd213sd	xmm0, xmm1, qword ptr [rip + .LCPI12_799] # xmm0 = (xmm1 * xmm0) + mem
	vfmadd213sd	xmm0, xmm1, qword ptr [rip + .LCPI12_800] # xmm0 = (xmm1 * xmm0) + mem
	vfmadd213sd	xmm0, xmm1, qword ptr [rip + .LCPI12_801] # xmm0 = (xmm1 * xmm0) + mem
	ret

Как увеличить стек FPU

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

Как увеличить стек FPU

Красивый код.

static double erfcx_y100(double y100)
{
  switch ((int) y100) {
case 0: {
double t = 2*y100 - 1;
return 0.70878032454106438663e-3 + (0.71234091047026302958e-3 + (0.35779077297597742384e-5 + (0.17403143962587937815e-7 + (0.81710660047307788845e-10 + (0.36885022360434957634e-12 + 0.15917038551111111111e-14 * t) * t) * t) * t) * t) * t;
}
...
  }
  // we only get here if y = 1, i.e. |x| < 4*eps, in which case
  // erfcx is within 1e-15 of 1..
  return 1.0;
}

LLVM 10 (-O3 -march=skylake) превращает switch со 100 ветками в переход по таблице:

_ZL10erfcx_y100d:                       # @_ZL10erfcx_y100d
	.cfi_startproc
# %bb.0:
	vcvttsd2si	eax, xmm0
	cmp	eax, 99
	ja	.LBB12_1
# %bb.2:
	jmp	qword ptr [8*rax + .LJTI12_0]
.LBB12_3:
	vaddsd	xmm0, xmm0, xmm0
	vaddsd	xmm0, xmm0, qword ptr [rip + .LCPI12_793]
	vmulsd	xmm1, xmm0, qword ptr [rip + .LCPI12_794]
	vaddsd	xmm1, xmm1, qword ptr [rip + .LCPI12_795]
	vmulsd	xmm1, xmm0, xmm1
	vaddsd	xmm1, xmm1, qword ptr [rip + .LCPI12_796]
	vmulsd	xmm1, xmm0, xmm1
	vaddsd	xmm1, xmm1, qword ptr [rip + .LCPI12_797]
	vmulsd	xmm1, xmm0, xmm1
	vaddsd	xmm1, xmm1, qword ptr [rip + .LCPI12_798]
	vmulsd	xmm1, xmm0, xmm1
	vaddsd	xmm1, xmm1, qword ptr [rip + .LCPI12_799]
	vmulsd	xmm0, xmm0, xmm1
	vaddsd	xmm0, xmm0, qword ptr [rip + .LCPI12_800]
	ret
...
	.section	.rodata,"a",@progbits
	.p2align	3
.LJTI12_0:
	.quad	.LBB12_3
	.quad	.LBB12_4
...

Кстати, если уж мы говорим о точности, мне удивительно, что в этом коде не используются инструкции FMA.

Как увеличить стек FPU

Собственно, это уже реализовано в стандартной библиотеке языка C. В частности, реализация синуса в glibc: https://github.com/lattera/glibc/blob/master/sysdeps/ieee754/dbl-64/s_sin.c

Information

Rating
Does not participate
Registered
Activity