Il parait qu'avec le langage C++ on peut écrire du code
Pourtant le langage est une hydre protozoaire... Donc
Serge « sans paille » Guelton
Apprendre à communiquer avec le meilleur ami du langage
CPPP — 15 juin 2019
Houat else?
#include <iostream> int main(int argc, char** argv) { long s = 0; while (std::cin) { long tmp = 0; std::cin >> tmp; s += tmp; } std::cout << s << std::endl; return 0; }
import sys print(sum(int(x) for x in sys.stdin.readlines()))
$ seq 1000000 > numbers $ clang++ sum.cpp -o sum $ time ./sum < numbers 0.61s user 0.01s system 94% cpu 0.659 total $ time python sum.py < numbers 0.77s user 0.04s system 99% cpu 0.818 total
L'utilisateur n'a pas précisé son intention
$ clang++ -O2 sum.cpp -o sum $ time ./count < numbers 0.34s user 0.00s system 99% cpu 0.348 total
# ## # ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # ## ## ## ## ## ## PERF DEBUG ÉDITION SÉCU TAILLE
« Je veux que le code généré soit efficace »
« Je veux que le code généré soit facile à déverminer »
$ curl $sq | clang -xc -c -g - -o sq.o $ objdump -h sq.o | grep debug # name size ... 9 .debug_str 00012b2d ... 10 .debug_abbrev 0000038d ... 11 .debug_info 0005056c ... 12 .debug_ranges 00000240 ... 13 .debug_macinfo 00000001 ... 14 .debug_pubnames 0000c73a ... 15 .debug_pubtypes 00001068 ... 19 .debug_line 00073402 ...
« Je veux me protéger de moi-même »
$ clang -xc -c -O2 - -S -emit-llvm -o \ - -D_FORTIFY_SOURCE=2 << EOF #include <stdio.h> void foo(char *s) { printf(s, s); } EOF define void @foo(i8*) { %2 = tail call i32 (i32, i8*, ...) \ @__printf_chk(i32 1, i8* %0, i8* %0) ret void }
« Je veux un binaire de petite taille »
$ curl $sq|clang -xc - -O2 -c -o-|wc -c 1488400 $ curl $sq|clang -xc - -Os -c -o-|wc -c 850696 $ curl $sq|clang -xc - -Oz -c -o-|wc -c 796976
$ cat hello.cpp #include <iostream> int main(int argc, char**argv) { std::co $ clang++ -Xclang \ -code-completion-at=hello.cpp:3:10 \ -fsyntax-only hello.cpp COMPLETION: codecvt : codecvt<<#typename _InternT#>, <#typename _ExternT#>, <#typename _StateT#>> COMPLETION: codecvt_base : codecvt_base ... COMPLETION: cout : [#ostream#]cout
Debug vs Size
$ for g in 1 2 3 "" do printf "-g$g: \t" && \ curl $sq|clang -c -O2 -g$g -xc - -o-|\ wc -c done -g1 : 3168632 -g2 : 7025488 -g3 : 7025488 -g : 7025488
Bonus : -fdebug-macro -g : 7167752
$ for O in 0 1 2 3 do /usr/bin/time -f "-O$O: %e s" \ clang sqlite3.c -c -O$O done -O0: 22.15 s -O1: 24.02 s -O2: 22.68 s -O3: 22.36 s
exercice : proposez une explication
Précision vs Performance
$ clang -xc - -o- -S -emit-llvm -O2 \ -freciprocal-math << EOF double rm(double x) { return x / 10.; } EOF define double @rm(double) { %2 = fmul arcp double %0, 1.000000e-01 ret double %2 }
$ clang -xc++ - -o- -S -emit-llvm \ -Ofast << EOF #include <numeric> #include <vector> using namespace std; double acc(vector<double> const& some) { return accumulate( some.begin(), some.end(), 0.); } EOF ... %95 = fadd fast <2 x double> %94, %93 ...
Pourquoi la vectorisation est-elle légale ici ?
Portabilité vs Performance
$ clang++ -O2 -S -o- -march=native \ -ffp-contract=fast << EOF double fma(double x, double y, double z) { return x + y * z; } EOF ... vfmadd213sd %xmm0, %xmm2, %xmm1
Performance vs Sureté
// mem.cpp #include <memory> double x(std::unique_ptr<double> y) { return *y; }
QUIZZ : combien de déréférencements ?
$ clang++ -fsanitize=address mem.cpp -S -emit-llvm -o- -O2
... %h = getelementptr inbounds %"class.std::unique_ptr", %"class.std::unique_ptr"* %y, i64 0, i32 0, i32 0, i32 0, i32 0, i32 0 %1 = ptrtoint double** %h to i64 %2 = lshr i64 %1, 3 %3 = add i64 %2, 2147450880 %4 = inttoptr i64 %3 to i8* %5 = load i8, i8* %4 %6 = icmp ne i8 %5, 0 br i1 %6, label %7, label %8 ; <label>:7: call void @__asan_report_load8(i64 %1) call void asm sideeffect "", ""() unreachable ; <label>:8: %9 = load double*, double** %h, align 8, !tbaa !2
$ clang --autocomplete=-std=, ... c++2a ... cuda ... gnu1x ... iso9899:2011
Security
$ clang -O2 -fstack-protector-all -S \ -o- -xc++ - << EOF #include <array> using namespace std; auto access(array<__int128_t, 10> a, unsigned i) { return a[i]; } EOF ... cmpq (%rsp), %rcx jne .LBB0_2 popq %rcx retq .LBB0_2: callq __stack_chk_fail
P rofile G uided O ptimisation
⇒ Influe sur
L ink T ime O ptimisation
$ echo 'foo() { return 0;}' | \ clang -flto -O2 -xc - -c -ofoo.o $ file foo.o foo.o: LLVM bitcode
Rubrique à brac
Pour ne pas optimiser certaines fonctions (e.g. pour du debug) :
#pragma clang optimize off ... #pragma clang optimize on
Pour bien optimiser ses boucles :
#pragma clang loop unroll(enable|full)
#pragma clang loop unroll_count(8)
#pragma clang loop distribute(enable)
#pragma clang loop vectorize_width(4)
Pour la précision :
#pragma clang fp contract(fast)
Pour l'éditeur de lien :
#pragma clang section bss="myBSS" \ data="myData" \ rodata="myRodata" \ text="myText"
#if __has_attribute(always_inline) #if __has_builtin(__builtin_trap) #if __has_include("myinclude.h") __clang__ typedef float float4 \ __attribute__((ext_vector_type(4))); __fp16 __is_pod (GNU, Microsoft)
// d.cpp double x(double* y, bool cond) { if(cond) delete y; bool ncond = !cond; if(ncond) return 1.; else return *y; }
$ clang++ --analyze -Xanalyzer -analyzer-output=text d.cpp d.cpp:8:12: warning: Use of memory after it is freed return *y; ^~ d.cpp:2:6: note: Assuming 'cond' is not equal to 0 if(cond) ^~~~ d.cpp:2:3: note: Taking true branch if(cond) ^ d.cpp:3:5: note: Memory is released delete y; ^~~~~~~~ d.cpp:5:3: note: Taking false branch if(ncond) ^ d.cpp:8:12: note: Use of memory after it is freed return *y;
Un compilateur un peu lent :
Une optimisation qui aurait mal tournée
$ { clang -xc++ - -c \ -O2 -Rpass=inline << EOF #include <numeric> #include <vector> using namespace std; double acc(vector<double> const& some) { return accumulate( some.begin(), some.end(), 0.); } EOF } 2>&1 | c++filt ... ... remark: __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >::__normal_iterator(double const* const&) \ ... inlined into std::vector<double, std::allocator<double> >::begin() const with cost=-40 (threshold=337) [-Rpass=inline]
$ clang --autocomplete=- | wc -l 2847
En compilation comme dans la vie, il faut une forme de balance
Space | Forward |
---|---|
Right, Down, Page Down | Next slide |
Left, Up, Page Up | Previous slide |
G | Go to slide number |
P | Open presenter console |
H | Toggle this help |