- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
// https://www.linux.org.ru/forum/development/15496357
// Нужен нормальный способ сказать компилятору что type aliasing невозможен на некотором участке кода. Минимальный пример:
template<typename T> struct f final {
void bad(T v) noexcept { while (b != e) *b++=v; }
void good(T v) noexcept {
auto tb(b), te(e);
while (tb != te) *tb++=v;
b=tb;
e=te;
}
T* b, * e;
};
template struct f<char>;
/*
Выхлоп gcc-8:
$ g++ -xc++ -std=c++14 -pedantic-errors -Os -c -of.o f.cc
$ objdump -Cd f.o
f.o: file format elf64-x86-64
Disassembly of section .text._ZN1fIcE3badEc:
0000000000000000 <f<char>::bad(char)>:
0: 48 8b 07 mov (%rdi),%rax
3: 48 3b 47 08 cmp 0x8(%rdi),%rax
7: 74 0c je 15 <f<char>::bad(char)+0x15>
9: 48 8d 50 01 lea 0x1(%rax),%rdx
d: 48 89 17 mov %rdx,(%rdi)
10: 40 88 30 mov %sil,(%rax)
13: eb eb jmp 0 <f<char>::bad(char)>
15: c3 retq
Disassembly of section .text._ZN1fIcE4goodEc:
0000000000000000 <f<char>::good(char)>:
0: 48 8b 07 mov (%rdi),%rax
3: 48 8b 57 08 mov 0x8(%rdi),%rdx
7: 48 39 d0 cmp %rdx,%rax
a: 74 09 je 15 <f<char>::good(char)+0x15>
c: 48 ff c0 inc %rax
f: 40 88 70 ff mov %sil,-0x1(%rax)
13: eb f2 jmp 7 <f<char>::good(char)+0x7>
15: 48 89 07 mov %rax,(%rdi)
18: 48 89 47 08 mov %rax,0x8(%rdi)
1c: c3 retq
*/
f<char>::bad(char)+0, f<char>::bad(char)+3 и f<char>::bad(char)+d - три раза за итерацию лезет в память. Разумеется, подобный код сливает в тестах производительности. Есть решение лучше, чем локальные переменные заводить каждый раз?
j123123 28.01.2020 19:34 # 0
3.14159265 28.01.2020 19:53 # +2
Н-н-н-нооо позвольте, где здесь С++, j123123?!это же чистая сишка.
j123123 28.01.2020 19:57 # 0
3.14159265 28.01.2020 19:58 # +2
bormand 28.01.2020 20:01 # +1
j123123 28.01.2020 20:06 # +2
то тогда GCC соптимизирует в memset:
Именно поэтому я за нормальные функции, а не всякое говно
bormand 28.01.2020 20:11 # +1
3.14159265 28.01.2020 20:16 # +1
https://godbolt.org/z/Ne28Mq
Но код good vs bad и так неэквивалентен.
Т.к. j123123 возможно привык жить в однопоточном мирке.
j123123 28.01.2020 20:18 # 0
j123123 28.01.2020 20:16 # 0
3.14159265 28.01.2020 20:20 # 0
В случае bad ему явно говорят: инкременти указатель в структуре на каждой итерации.
В случае good ему явно говорят: скопируй себе указатель, поитерируй и поменяй его в конце цикла.
Понимаю что в царском мире, где у процессора одно ядро, а потоки не нужны, оба случая кажутся эквивалентными.
Однако это не так, ибо в многопоточном коде различие СУЩЕСТВЕННОЕ.
bormand 28.01.2020 20:25 # +1
Он именно в своём единственном треде ссыт затереть b или e во время записи в *b.
3.14159265 28.01.2020 20:30 # 0
j123123 28.01.2020 20:33 # 0
специализировать типом int, крестоговнокомпилятор не будет предполагать что он перепишет хуйней "while (b != e) *b++=v;" хуйню "T* b, * e;" в этой говноструктуре
bormand 28.01.2020 20:35 # +1
j123123 28.01.2020 20:36 # 0
Desktop 28.01.2020 20:06 # +1
j123123 28.01.2020 20:09 # 0
bormand 28.01.2020 20:09 # 0
HoBorogHuu_nemyx 28.01.2020 20:19 # 0
3.14159265 28.01.2020 21:46 # +2
6.5 Expressions
3.14159265 28.01.2020 20:33 # 0
Но на ЛОРе правильно сказали. Это сишка.
Человек пытался писать на крестах как на сишке. Ну и получил. Ещё по-божески.
bormand 28.01.2020 20:33 # 0
bormand 28.01.2020 20:44 # 0
// Specialization: for char types we can use memset
(и это не шутка, там реально специализация через мемсет)
j123123 28.01.2020 20:46 # 0
3.14159265 28.01.2020 20:59 # 0
И оно будет так же криво оптимизироваться.
Арифметика указателей, структуры, сhar. Кресты здесь причём?
j123123 28.01.2020 21:01 # 0
Если б я этот код запостил как код на Си, мне б сказали что тут template<typename T> а в Си такого нет.
3.14159265 28.01.2020 21:05 # 0
template тут не при чём.
j123123 28.01.2020 21:09 # 0
> Тоесть, смотрите, как ведет себя настоящий, состоявшийся, знающий себе цену программист? А он ведет себя очень просто: плюсы - говно, но и си - говно, кричит он громко, ничуть не смущаясь подходящих к нему слева - одептов плюсов, а справа - почетателей битоебского низкоуровневого язычка типа Си
bormand 28.01.2020 21:11 # 0
3.14159265 28.01.2020 21:22 # 0
Или там перепитушни много?
bormand 28.01.2020 20:07 # 0
3.14159265 28.01.2020 21:02 # 0
Алиас явно и чётко показывает идею - входящий елемент - есть алиас исходящего, как ссылка в путих С++. А с указателем ты такую фигню не сделаешь - только указатель на указатель.
Аналогов биндов вообще нет, кроме того, что я наваял в первой портянке. Либо юзать структуры и питухуказатели, но это слишком тормазная питушня.
Поэтому алиасы и указатели совершенно разные вещи, а бинды и кастыли со структурами - тоже разные вещи, ибо кастыли со структурами - питушня.
j123123 28.01.2020 21:03 # 0
3.14159265 28.01.2020 21:07 # +1
Всё должно отражать всё - если твоей конпелятор написан как говно - он и оптимизировать будет как говно. И да, оптимизации не нужны я уже не помню где был тред, помоему на лоре.
Вобще для моего мегаязыка оптимизации не нужны, ибо оптимизации нужны для питухов - там будет удобная ручная предсказуемость, как в ассемблере.
В место питушских переменных - там буду переменные, который на самом деле по умолчанию безымянные регистры. Явный их биндинг на имена, явный ялиасинг. Никаких стеков и прочей ереси.
Никаких автовекторизаций циклов( которые в 50% дают деградацию, допустим гцц(и все другие конпеляторы) по умолчанию вместо стекового фпу года гинерят ссе код, который медленее фпушного и теряют 10-30% производительности.
Никаких разворачиваний циклов - нормальная автогинерациия кода в компилтайме, а не питушнян а шаблонах как в С++ и не ущербные макросы.
Истинный компилтайм - для кода не будет существовать разницы между рантаймом и компилтаймом. Будет рантайм во время конпеляции - код будет сам гинерить то, что ему нужно.
Ты пишешь char m[] = f(); в функции ты реализуешь заполнении массива, а конпелятор её исполняет. Нал оре был целый тред про constexp или как там его.
Никаких оптимизаций циклов, никакой питушни - ты либо сам умеешь писать нормально циклы - либо иди в С++. Там за тебя в 20% случаев конпелятор заменит питушню на for(i) for(j) for(k) - на нормальный цикл на указателях, который работает в 3раза быстрее.
И ещё масса всего - все эти оптимизации от бешенства с жиру - глянь на царский код, ему не нужны никакие оптимизации, кроме алиасинга( и то это из-за особенностей сишки).
j123123 28.01.2020 21:11 # 0
Это справедливо только для классической питушни с адресным пространством, а есть еще всякие data-flow архитектуры, в которых адресуемой памяти вообще нихуя нет. В частности, для dataflow архитектур (которые очень часто реализуются поверх FPGA) применяются свои особые языки https://habrahabr.ru/post/122479/ вот статья со швабры например.
gost 28.01.2020 21:12 # +1
3.14159265 28.01.2020 21:16 # +1
AnalBoy 28.01.2020 21:26 # 0
человек-компилятор
человек-отладчик
человек-дизассемблер
человек-интерпретатор
Stallman 28.01.2020 21:45 # 0
AnalBoy 28.01.2020 22:53 # 0