PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ZeroW Performance



Holomino
31.10.2018, 17:46
33730

Hallöle,

mag mir vielleicht jemand spontan mit seinem großen Raspi unter die Arme greifen und die im Anhang aufgeführten Dateien in einen C-Compiler schmeißen und als Release durchlaufen lassen?

Ich bekomme mit meinem ZeroW so etwa 3,5s für einen Durchlauf raus. Kommt mir etwas viel vor.


Danke
Holomino

Holomino
01.11.2018, 16:40
33733

Mit nem 3B+ bitte????

NumberFive
16.11.2018, 07:20
gcc main.c BresenhamTest.c Bresenham.c -o test.bin -mtune=native -O2

Dann komme ich auf eine 2er auf diese Zeiten

Bresenham time: 2.839819
Press e to exit, anything else to repeat

Bresenham time: 2.808073
Press e to exit, anything else to repeat
t

Bresenham time: 2.843296
Press e to exit, anything else to repeat
e
Bresenham time: 2.808091
Press e to exit, anything else to repeat

Holomino
17.11.2018, 07:32
Hmmm,
mit nem BPI M2 Zero liege ich jetzt bei 2,5s. Der taktet so bei 960MHz im Normalbetrieb.

Aber schon etwas seltsam: Auf'm Notebook(1,8GHz) habe ich ne Durchlaufzeit von 0,2s.
Da alle Operationen im Ganzzahlbereich liegen und auch nur ein Kern involviert ist, hätte ich jetzt eher gedacht, das lässt sich grob linear anhand der Prozessorfrequenz schätzen - aber hier liegt die Abweichung bei Faktor 5?!? Was treibt der ARM da?

NumberFive
18.11.2018, 08:58
Ich habe mir den Code nicht wirklich angesehen nur Compiliert. Was ist der Ziel des Codes ? Malen von Kreisen ?
Für mein Projekt habe ich da auch mal angefangen aber habe zur zeit aufgeben jetzt sind alle Steuerelementebilder das geht einfach viel schneller. Problem leider nicht wirklich skalierbar ohne das es blöd aussieht. Wenn alles mal Funktioniert will svg noch mal versuchen.

Muss es C sein ? oder darf es auch C++ sein ?

http://www.cplusplus.com/reference/cmath/abs/

Das ist für mich fliescomma damit geht er auf die FPU ergo da kann man vielleicht noch was raus holen.
https://stackoverflow.com/questions/16499475/arm-assembly-absolute-value-function-are-two-or-three-lines-faster

int err = (dx > dy ? dx : -dy) / 2, e2;
Hier verlassen mich meine C erkenntnisse was macht die Zeile ? , e2 verstehe ich nicht

Holomino
18.11.2018, 11:16
Doch, den kennst Du auch:

int err, e2;
int err= 0, e2;
int err= irgendwas, e2;

Aber ich muss lachen, den Code hab ich von irgendwo geklaut und ich habe auch ziemlich lange auf die Zeile gestarrt, bis endlich der Groschen fiel.

Der Bresenham ist in der Form nen Linienerzeuger, der steppt nur die Punkte von Start bis End durch. Ganz gut für nen Laserscanner im GridSlam zu gebrauchen (Wenn man denn im Callback auch mit den Gridzellen vergleicht oder sie setzt).

Allerdings war die Sache für mich auch nur ein Test, um mal zu sehen, was aus diesen kleinen PI-Dingern rauszuholen ist. Ich habe meine App mittlerweile mit C# unter Mono recht gut mit dem BPI M2 Zero am laufen (nachdem ich nun auch mal die Rechnerei auf die Kerne verteilt habe). Mit dem RPI ZeroW wird's rein rechnerisch unter Mono nix, wenn ich sehe, dass alle vier Kerne des BPI zur Zeit bei etwa 50% liegen. Den ganzen Sermon für das Raspi-Geklüngel auf C zu portieren würde sicher die Sache um den Faktor 3..4 beschleunigen, lohnt sich aber für mich irgendwie (noch) nicht. Ich hänge hier sowieso 90% der Zeit mit nem Notebook lokal in Simulationen oder über Bluetooth am Roboter.

Ich nehme das jetzt einfach mal zur Kenntnis mit dem (nicht repräsentativen) BresenhamTest:
Faktor Arm Mono : Arm C 4:1
Faktor Windows C : Arm C 1:5
Faktor Windows C : Windows C# 1:4

NumberFive
19.11.2018, 06:25
Ok jetzt habe ich das auch verstanden. Danke.
Dann lassen wir das Thema wie es ist. Ich mag es zwar nicht so Energie zu verschwenden aber das dein Projekt und ich sollte meines voran treiben.
Ich programmiere jeden Tag C# (Job) aber ich mag es nach wie vor nur bedingt das krass Beispiel die Farbe aus eine Bitmap rechnen (Graustufen A3 200 Dpi). C# 30 msec C++ 3 msec Windows 8 Kerne 16 GByte Hauptspeicher.

Holomino
19.11.2018, 14:50
Es gibt da tatsächlich nur eine Hand voll Dinge, die mich an C# festhalten lassen: PropertyGrid(zur Konfiguration auch während der laufenden Simulation), XMLSerializer(zum Laden/Speichern von Konfigurationen), Reflection (zum Durchforsten/Laden/Speichern von externen DLLs per Latebinding),....
Das mag ich nicht mehr missen. Ich bin mittlerweile einfach zu faul oder zu alt, Konfigurationsdialoge zu malen oder in Dateien per Hand rumzuhacken.

Aber man kann ja auch den rechenlastigen Teil in den unmanaged-Bereich auslagern, wenn es nötig wird.

NumberFive
19.11.2018, 18:21
für Config files nehme ich Json https://github.com/nlohmann/json/releases.
Zu dem rest sage ich mal nix.

Holomino
19.11.2018, 21:44
http://www.cplusplus.com/reference/cmath/abs/

Das ist für mich fliescomma damit geht er auf die FPU ergo da kann man vielleicht noch was raus holen.


BTW: In der Bresenham-Funktion wird das "abs" einmalig aufgerufen, wenn Du in BresenhamTest die Anzahl der Aufrufe kleiner machst (/100) und die Länge der Linien entsprechend vergrößerst (*100), macht das zumindest bei mir in der Durchlaufzeit null Unterschied.

An der FPU liegt das also hier nicht.

NumberFive
20.11.2018, 05:36
Hast du eine einfach Möglichkeit das Ergebnis zu prüfen ?
vielleicht habe ich ja Zeit mir das noch mal anzusehen den ich glaube so ganz egal ist es dir doch nicht oder ?

Holomino
20.11.2018, 13:28
Ähh,
mir gings eigentlich nicht um die Optimierung.

Mir gings um die Begründung, warum ein kleines Stück Algorithmus, dessen Hauptanteil sich aus einfacher Registerlogik (Subtraktion, Addition, Inkrementierung, Dekrementierung) im 32-Bit-Bereich zusammensetzt, auf dem einen System nominal 5x langsamer abläuft.

In der while-Schleife in Bresenham steht doch nun wirklich nix, was sich nicht 1:1 in Assembler umsetzen lässt.

Kurz: Halte doch mal die beiden ASM-Listings unten nebeneinander und erklär mir, warum der eine Code auf'm Notebook bei 1,8Ghz in 0,2s durchläuft und der andere Code auf'm ARM mit knapp 1GHz 2,5 s braucht.

So schlecht kann ein Befehlssatz doch nicht implementiert sein, da steckt doch bestimmt noch irgendwas mit Wartezyklen oder Speichercaches dahinter.

Ich verstehe es (noch) nicht so ganz. Da hänge ich mental gerade etwas fest.


g++ -S Bresenham.c auf'm Notebook


.file "Bresenham.c"
.text
.globl _Z9Bresenham8IPoint_tS_PFviiE
.def _Z9Bresenham8IPoint_tS_PFviiE; .scl 2; .type 32; .endef
.seh_proc _Z9Bresenham8IPoint_tS_PFviiE
_Z9Bresenham8IPoint_tS_PFviiE:
.LFB4:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $80, %rsp
.seh_stackalloc 80
.seh_endprologue
movq %rcx, 16(%rbp)
movq %rdx, 24(%rbp)
movq %r8, 32(%rbp)
movl 16(%rbp), %eax
movl %eax, -4(%rbp)
movl 20(%rbp), %eax
movl %eax, -8(%rbp)
movl 24(%rbp), %eax
movl %eax, -16(%rbp)
movl 28(%rbp), %eax
movl %eax, -20(%rbp)
movl -16(%rbp), %eax
subl -4(%rbp), %eax
movl %eax, %edx
movl %edx, %eax
sarl $31, %eax
xorl %eax, %edx
movl %edx, -24(%rbp)
subl %eax, -24(%rbp)
movl -4(%rbp), %eax
cmpl -16(%rbp), %eax
jge .L2
movl $1, %eax
jmp .L3
.L2:
movl $-1, %eax
.L3:
movl %eax, -28(%rbp)
movl -20(%rbp), %eax
subl -8(%rbp), %eax
movl %eax, %edx
movl %edx, %eax
sarl $31, %eax
xorl %eax, %edx
movl %edx, -32(%rbp)
subl %eax, -32(%rbp)
movl -8(%rbp), %eax
cmpl -20(%rbp), %eax
jge .L4
movl $1, %eax
jmp .L5
.L4:
movl $-1, %eax
.L5:
movl %eax, -36(%rbp)
movl -24(%rbp), %eax
cmpl -32(%rbp), %eax
jg .L6
movl -32(%rbp), %eax
negl %eax
movl %eax, %edx
shrl $31, %edx
addl %edx, %eax
sarl %eax
jmp .L7
.L6:
movl -24(%rbp), %eax
movl %eax, %edx
shrl $31, %edx
addl %edx, %eax
sarl %eax
.L7:
movl %eax, -12(%rbp)
.L12:
movl -8(%rbp), %edx
movl -4(%rbp), %ecx
movq 32(%rbp), %rax
call *%rax
movl -4(%rbp), %eax
cmpl -16(%rbp), %eax
jne .L8
movl -8(%rbp), %eax
cmpl -20(%rbp), %eax
je .L14
.L8:
movl -12(%rbp), %eax
movl %eax, -40(%rbp)
movl -24(%rbp), %eax
negl %eax
cmpl -40(%rbp), %eax
jge .L10
movl -32(%rbp), %eax
subl %eax, -12(%rbp)
movl -28(%rbp), %eax
addl %eax, -4(%rbp)
.L10:
movl -40(%rbp), %eax
cmpl -32(%rbp), %eax
jge .L12
movl -24(%rbp), %eax
addl %eax, -12(%rbp)
movl -36(%rbp), %eax
addl %eax, -8(%rbp)
jmp .L12
.L14:
nop
nop
addq $80, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (tdm64-1) 5.1.0"



gcc -S Bresenham.c auf BPI


.arch armv6
.eabi_attribute 27, 3
.eabi_attribute 28, 1
.fpu vfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "Bresenham.c"
.text
.align 2
.global Bresenham
.type Bresenham, %function
Bresenham:
@ args = 4, pretend = 0, frame = 56
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
add fp, sp, #4
sub sp, sp, #56
sub ip, fp, #52
stmia ip, {r0, r1}
sub r1, fp, #60
stmia r1, {r2, r3}
ldr r3, [fp, #-52]
str r3, [fp, #-8]
ldr r3, [fp, #-48]
str r3, [fp, #-12]
ldr r3, [fp, #-60]
str r3, [fp, #-20]
ldr r3, [fp, #-56]
str r3, [fp, #-24]
ldr r2, [fp, #-20]
ldr r3, [fp, #-8]
rsb r3, r3, r2
cmp r3, #0
rsblt r3, r3, #0
str r3, [fp, #-28]
ldr r2, [fp, #-8]
ldr r3, [fp, #-20]
cmp r2, r3
bge .L2
mov r3, #1
b .L3
.L2:
mvn r3, #0
.L3:
str r3, [fp, #-32]
ldr r2, [fp, #-24]
ldr r3, [fp, #-12]
rsb r3, r3, r2
cmp r3, #0
rsblt r3, r3, #0
str r3, [fp, #-36]
ldr r2, [fp, #-12]
ldr r3, [fp, #-24]
cmp r2, r3
bge .L4
mov r3, #1
b .L5
.L4:
mvn r3, #0
.L5:
str r3, [fp, #-40]
ldr r2, [fp, #-28]
ldr r3, [fp, #-36]
cmp r2, r3
bgt .L6
ldr r3, [fp, #-36]
rsb r3, r3, #0
mov r2, r3, lsr #31
add r3, r2, r3
mov r3, r3, asr #1
b .L7
.L6:
ldr r3, [fp, #-28]
mov r2, r3, lsr #31
add r3, r2, r3
mov r3, r3, asr #1
.L7:
str r3, [fp, #-16]
.L12:
ldr r3, [fp, #4]
ldr r0, [fp, #-8]
ldr r1, [fp, #-12]
blx r3
ldr r2, [fp, #-8]
ldr r3, [fp, #-20]
cmp r2, r3
bne .L8
ldr r2, [fp, #-12]
ldr r3, [fp, #-24]
cmp r2, r3
bne .L8
b .L13
.L8:
ldr r3, [fp, #-16]
str r3, [fp, #-44]
ldr r3, [fp, #-28]
rsb r2, r3, #0
ldr r3, [fp, #-44]
cmp r2, r3
bge .L10
ldr r2, [fp, #-16]
ldr r3, [fp, #-36]
rsb r3, r3, r2
str r3, [fp, #-16]
ldr r2, [fp, #-8]
ldr r3, [fp, #-32]
add r3, r2, r3
str r3, [fp, #-8]
.L10:
ldr r2, [fp, #-44]
ldr r3, [fp, #-36]
cmp r2, r3
bge .L11
ldr r2, [fp, #-16]
ldr r3, [fp, #-28]
add r3, r2, r3
str r3, [fp, #-16]
ldr r2, [fp, #-12]
ldr r3, [fp, #-40]
add r3, r2, r3
str r3, [fp, #-12]
.L11:
b .L12
.L13:
sub sp, fp, #4
@ sp needed
ldmfd sp!, {fp, pc}
.size Bresenham, .-Bresenham
.ident "GCC: (Raspbian 4.9.2-10+deb8u1) 4.9.2"
.section .note.GNU-stack,"",%progbits


BTW: Du kannst mal zum Spielen im BresenhamTest die sum aus dem Callback mit als Ergebnis ausgeben lassen. Daran sieht man zumindest, dass der Algorithmus was tut und nicht wegoptimiert wird.

Holomino
20.11.2018, 17:05
So, wieder was gelernt:

Nachdem mir nun auch auffiel, dass bei den Zeiten auf'm Notebook rein rechnerisch ein Callbackaufruf so etwa ein bis zwei CPU-Takte beansprucht (irgendwie komisch bei der Länge des Listings), hab ich's noch mal nachgeschlagen: Das moderne CPU-Gedöns hat nen internen 16fach Clock-Multiplier (https://en.wikichip.org/wiki/intel/core_i5/i5-8250u). Mit den IPCs (https://en.wikipedia.org/wiki/Instructions_per_cycle) scheinen die Intels doch irgendwie vorne zu liegen.

Der ARM ist also nicht so langsam, sondern das Notebook so fix!