Benutzen wir Julia, können wir mittels Introspection ansehen, was für Code LLVM aus unseren Beispielen zaubert. Dazu definieren wir zunächst wieder die zwei Varianten unseres max-Beispiels:
function max(a,b) if(a>b) return a else return b endMittels code_native(max,(Int,Int)) bzw code_native(max1,(Int,Int)) können wir uns nun ansehen, was LLVM für Code daraus produziert - zunächst wieder die "normale" Variante:function max1(a,b) return a*(a>b)+b*(a<=b) end
code_native(max,(Int,Int)) .text Filename: promotion.jl Source line: 239 pushq %rbp movq %rsp, %rbp cmpq %rdi, %rsi Source line: 239 cmovgeq %rsi, %rdi movq %rdi, %rax popq %rbp retUnd die branchless-Variante:
code_native(max1,(Int,Int)) .text Filename: none Source line: 2 pushq %rbp movq %rsp, %rbp xorl %eax, %eax cmpq %rsi, %rdi Source line: 2 movq %rsi, %rcx cmovgq %rax, %rcx cmpq %rdi, %rsi cmovlq %rdi, %rax addq %rcx, %rax popq %rbp retHier zeigt sich wieder, was wir bereits mit GCC auf x86 und ARM festgestellt haben: Triviale Beispiele behandelt der Compiler effektiver als es unser Code aus der Manufaktur kann. Wie sieht es aber mit dem nicht mehr so trivialen Beispiel aus?
function nontriv(a) for i in 1:length(a) pointedAt=a[i] if((pointedAt>=97)&&(pointedAt<=122)) a[i]=pointedAt-32 end end endfunction nontriv1(a) for i in 1:length(a) pointedAt=a[i] x=((pointedAt>=97)&&(pointedAt<=122)) a[i]=pointedAt-(32*x) end end
Hier zeigt sich bei Aufruf von code_native(nontriv,(Tuple{Array{Int,1}})) zunächst erst einmal, dass es offenbar doch keine gute Idee war, die beiden Compiler mittels Abkürzung über Julias Introspect-Mechanismus vergleichen zu wollen: Dieser Mechanismus zeigt nicht einfach nur den Maschinencode, sondern tut offenbar noch mehr - anders ist nicht zu erklären, dass verschiedene Quelltext-Zeilen mehr als einmal im Ergebnis auftauchen:
code_native(nontriv,(Tuple{Array{Int,1}})) .text Filename: none Source line: 2 pushq %rbp movq %rsp, %rbp Source line: 2 movq 8(%rdi), %r9 xorl %ecx, %ecx testq %r9, %r9 movl $0, %eax cmovnsq %r9, %rax testq %rax, %rax je L123 Source line: 5 testq %r9, %r9 cmovsq %rcx, %r9 Source line: 2 negq %r9 Source line: 3 movq 8(%rdi), %r8 xorl %edx, %edx L47: cmpq %r8, %rcx jae L128 movq (%rdi), %r10 Source line: 5 leaq (,%rdx,8), %rax negq %rax Source line: 3 movq (%r10,%rax), %rax cmpq $97, %rax Source line: 4 jl L108 cmpq $122, %rax jg L108 Source line: 3 movq %rdx, %rsi negq %rsi Source line: 5 addq $-32, %rax movq %rax, (%r10,%rsi,8) L108: incq %rcx decq %rdx cmpq %rdx, %r9 jne L47 L123: movq %rbp, %rsp popq %rbp ret L128: movl $1, %eax Source line: 3 subq %rdx, %rax movq %rsp, %rcx leaq -16(%rcx), %rsi movq %rsi, %rsp movq %rax, -16(%rcx) movabsq $jl_bounds_error_ints, %rax movl $1, %edx callq *%raxAuch der Aufruf von code_native(nontriv1,(Tuple{Array{Int,1}})) zeigt dieses Verhalten: Manche Quelltextzeilen tauchen mehrfach auf. Insgesamt ist das Ergebnis länger als für nontriv, allerdings hat das wahrscheinlich keine Aussagekraft. Daher wurde es wohl oder übel notwendig, LLVM zu installieren und es auf den C-Quelltext anzusetzen...
code_native(nontriv1,(Tuple{Array{Int,1}})) .text Filename: none Source line: 2 pushq %rbp movq %rsp, %rbp Source line: 2 movq 8(%rdi), %r9 xorl %r11d, %r11d testq %r9, %r9 movl $0, %eax cmovnsq %r9, %rax testq %rax, %rax je L138 Source line: 5 testq %r9, %r9 cmovsq %r11, %r9 Source line: 2 negq %r9 Source line: 3 movq 8(%rdi), %r8 xorl %edx, %edx L48: cmpq %r8, %r11 jae L143 Source line: 5 leaq (,%rdx,8), %r10 Source line: 3 movq (%rdi), %rax Source line: 5 subq %r10, %rax Source line: 3 movq (%rax), %rax xorl %esi, %esi cmpq $97, %rax Source line: 4 jl L100 cmpq $123, %rax setl %cl movzbl %cl, %esi shlq $5, %rsi Source line: 5 L100: cmpq 8(%rdi), %r11 jae L182 subq %rsi, %rax movq (%rdi), %rsi negq %r10 movq %rax, (%rsi,%r10) incq %r11 decq %rdx cmpq %rdx, %r9 jne L48 L138: movq %rbp, %rsp popq %rbp ret L143: movl $1, %eax Source line: 3 subq %rdx, %rax movq %rsp, %rcx leaq -16(%rcx), %rsi movq %rsi, %rsp movq %rax, -16(%rcx) movabsq $jl_bounds_error_ints, %rax movl $1, %edx callq *%rax L182: movl $1, %eax Source line: 5 subq %rdx, %rax movq %rsp, %rcx leaq -16(%rcx), %rsi movq %rsi, %rsp movq %rax, -16(%rcx) movabsq $jl_bounds_error_ints, %rax movl $1, %edx callq *%rax
Mercator-Projektion für generierte Planeten
22.05.2017
Nachdem ich neulich endlich auch die dreidimensionale Generierung von Spielwelten erfolgreich ausprobiert hatte, entwickelten sich notgedrungen neue Ideen für weitere Forschungen - eine davon möchte ich hier vorstellen:
Weiterlesen...Android Basteln C und C++ Chaos Datenbanken Docker dWb+ ESP Wifi Garten Geo Git(lab|hub) Go GUI Gui Hardware Java Jupyter Komponenten Links Linux Markdown Markup Music Numerik PKI-X.509-CA Python QBrowser Rants Raspi Revisited Security Software-Test sQLshell TeleGrafana Verschiedenes Video Virtualisierung Windows Upcoming...
Nach den diversen schlimmen Nachrichten Ende letzten Jahres (Log4Shell) habe ich den Entschluss gefasst, von Log4J Abschied zu nehmen und eine andere Logging-Lösung einzusetzen.
Weiterlesen...Ich habe mich bereits vor einigen Wochen mit diesem System beschäftigt - nun war es an der Zeit, ein wenig zu variieren...
Weiterlesen...Ich habe inzwischen in mehreren Projekten gearbeitet, die von sich behauptet haben, die agile Methodik zu nutzen und war damit nie wirklich glücklich. Jetzt kann ich die Gründe dafür beginnen, in Worte zu fassen:
Weiterlesen...Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.
Wer daran teilhaben und eventuell sogar davon profitieren möchte, muß damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.
Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...
PS: Meine öffentlichen GitHub-Repositories findet man hier.