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
end
function max1(a,b)
return a*(a>b)+b*(a<=b)
end
Mittels 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:
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
ret
Und 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
ret
Hier 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
end
function 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 *%rax
Auch 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
Fährnisse des Buildprozesses unter Windows
17.07.2019
Nachdem ich begonnen hatte, mich mit der Beschleunigung der Berechnung des Mandelbrot-Fraktals unter Zuhilfenahme der Shadereinheiten in Graphikkarten zu beschäftigen und erste Erfolge feiern konnte, wollte ich das mal auf einer richtigen Graphikkarte ausprobieren...
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...
Ich bin heute nochmal inspiriert worden, weiter über die Trojan Source Vulnerability nachzudenken. Meiner Meinung nach bestehen hier noch Probleme - speziell bei Nutzereingaben oder Daten, die über externe Schnittstellen ampfangen werden.
Weiterlesen...Ich habe die auf OpenStreetMap basierende OpenSource Navigationslösung Graphhopper in einen Docker-Container gepackt und als neuestes Mitglied in meinem Docker-Zoo willkommen geheißen.
Weiterlesen...Ich habe neulich über eine Möglichkeit berichtet, SQLite mittels der sQLshell und Beanshell-Skripten um SQL-Funktionen zu erweitern. In diesem Artikel versprach ich auch, über eine solche Möglichkeit für Aggregatfunktionen zu berichten.
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 - meine öffentlichen GitLab-Repositories finden sich dagegen hier.