Temat: wydajnościówka w Action!

tak sobie dzisiaj z Perinoidem porównywaliśmy wydajność prostego kodu w C i Action!

// powiel 40 bajtow cc65
    for(i=1; i<192; i++) {
        memcpy(ptr, video_ptr, 40);
        ptr+=40;
    }
; powiel 40 bajtow Action
FOR i=1 TO 192
   DO
          moveblock(ptr, video_ptr, 40)
          SCREEN==+40
   OD

dla ułatwienia - te same zmienne, typy etc. moveblock robi to samo co memcpy - czyli kopiuje zadaną liczbę bajtów na docelowe miejsce z wskazanego miejsca. Kopiowanie linii danych w pamięci ekranu - no i wydajnościowo - mówimy o mikroułamkach sekund, ale licząc ramki ekranu na grabberze to Action! robi to dokładnie dwa razy dłużej (0.2 sek. vs 0.1 sek.).

Pytanie - czy da się to szybciej w Action?

/|\ 800 Incognito+Supercard - 800XL - 1088XEL CF3 - XE GS Ultimate VBXE - SIO2SD - SIDE2 - CA2001 - 1050 - XF551 clone by Zaxon /|\ PORTFOLIO

2

Odp: wydajnościówka w Action!

kod memcpy CC65 jest mocno optymalizowany, korzystam z niego w MP (MadPascal)

; Ullrich von Bassewitz, 2003-08-20
; Performance increase (about 20%) by
; Christian Krueger, 2009-09-13

.proc    @moveu            ; assert Y = 0

ptr1    = edx
ptr2    = ecx
ptr3    = eax

    stx @sp

    ldy    #0

    ldx     ptr3+1        ; Get high byte of n
    beq     L2        ; Jump if zero

L1:     .rept 2            ; Unroll this a bit to make it faster...
    lda     (ptr1),Y    ; copy a byte
    sta     (ptr2),Y
    iny
    .endr

    bne     L1
    inc     ptr1+1
    inc     ptr2+1
    dex            ; Next 256 byte block
    bne    L1        ; Repeat if any

    ; the following section could be 10% faster if we were able to copy
    ; back to front - unfortunately we are forced to copy strict from
    ; low to high since this function is also used for
    ; memmove and blocks could be overlapping!
    ; {
L2:                ; assert Y = 0
    ldx     ptr3        ; Get the low byte of n
    beq     done        ; something to copy

L3:     lda     (ptr1),Y    ; copy a byte
    sta     (ptr2),Y
    iny
    dex
    bne     L3

    ; }

done    ldx #0
@sp    equ *-1
    rts
.endp


@move    .proc (.word ptr1, ptr2, ptr3) .var

ptr1    = edx
ptr2    = ecx
ptr3    = eax

src    = ptr1
dst    = ptr2
cnt    = ptr3

    cpw ptr2 ptr1
    scs
    jmp @moveu

    stx @sp

; Copy downwards. Adjust the pointers to the end of the memory regions.

    lda     ptr1+1
    add     ptr3+1
    sta     ptr1+1

    lda     ptr2+1
    add     ptr3+1
    sta     ptr2+1

; handle fractions of a page size first

    ldy     ptr3        ; count, low byte
    bne     @entry        ; something to copy?
    beq     PageSizeCopy    ; here like bra...

@copyByte:
    lda     (ptr1),y
    sta     (ptr2),y
@entry:
    dey
    bne     @copyByte
    lda     (ptr1),y    ; copy remaining byte
    sta     (ptr2),y

PageSizeCopy:            ; assert Y = 0
    ldx     ptr3+1        ; number of pages
    beq     done        ; none? -> done

@initBase:
    dec     ptr1+1        ; adjust base...
    dec     ptr2+1
    dey            ; in entry case: 0 -> FF
    lda     (ptr1),y    ; need to copy this 'intro byte'
    sta     (ptr2),y    ; to 'land' later on Y=0! (as a result of the '.repeat'-block!)
    dey            ; FF ->FE
@copyBytes:
    .rept 2            ; Unroll this a bit to make it faster...
    lda     (ptr1),y
    sta     (ptr2),y
    dey
    .endr
@copyEntry:            ; in entry case: 0 -> FF
    bne     @copyBytes
    lda     (ptr1),y    ; Y = 0, copy last byte
    sta     (ptr2),y
    dex            ; one page to copy less
    bne     @initBase    ; still a page to copy?

done    ldx #0
@sp    equ *-1
    rts
.endp
*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

3

Odp: wydajnościówka w Action!

robiłem też inne testy, i wyszło że zwykła pętla kopiująca musiałaby minimum po 4 bajty na raz kopiować aby prawie dorównać temu kodowi z cc65, w tym stylu

 lda (src),y
 sta (dst),y
 iny
 lda (src),y
 sta (dst),y
 iny
 lda (src),y
 sta (dst),y
 iny
 lda (src),y
 sta (dst),y
 iny
*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

4

Odp: wydajnościówka w Action!

aż odpalę zliczanie z zegarka, bo nie widzę po rysowaniu w pamięci, żeby to 4x szybciej było - ale dzięki za podpowiedź, muszę zmajstrować tak jak myślałem własną prockę do tego.

Oryginalnie zrobili to tak:

 PROC MoveBlock=*(BYTE POINTER d,s,CARD sz)
[$A085$A186$A284$A0$0$A5A5$16F0$A2B1$A091$C8$F9D0$A1E6$A3E6$A5C6$F1
D0$5F0$A2B1$A091$C8$A4C4$F7D0$60]
$664E P_MOVEBLOCK STA FRET
            STX FRET+1
STY BPTR2
LDY #$00
LDA L00A5
BEQ L6670
LDA (BPTR2),Y  
STA (FRET),Y
INY
BNE L665A
INC FRET+1
INC L00A3
DEC L00A5
BNE L665A
BEQ L6670
L666B       LDA (BPTR2),Y  
STA (FRET),Y
            INY
L6670       CPY L00A4
BNE L666B 
RTS

Ostatnio edytowany przez tooloudtoowide (2020-01-23 19:27:21)

/|\ 800 Incognito+Supercard - 800XL - 1088XEL CF3 - XE GS Ultimate VBXE - SIO2SD - SIDE2 - CA2001 - 1050 - XF551 clone by Zaxon /|\ PORTFOLIO

5

Odp: wydajnościówka w Action!

tooloudtoowide napisał/a:

Pytanie - czy da się to szybciej w Action?

Bez stosowania szczególnych rozwiązań - nie. Szczególne rozwiązanie to podmienić moveblock na to memcpy z cc65, i będzie tak samo szybko, lub napisać szybką procedurę "blit", która pobierze dodatkowe parametry i mieć możliwość kopiowania prostokąta za jednym wywołaniem.

Trzeba pamiętać, że protokół wywołania procedury w action różni się w zal. od liczby bajtów parametrów: do trzech bajtów parametrów - rejestry  axy. Powyżej - przez komórki pamięci na stronie zerowej (a już nie przez rejestry).

Ostatnio edytowany przez qbahusak (2020-01-24 10:46:35)

6

Odp: wydajnościówka w Action!

dzięki Kuba - z tym prostokątem to czytasz mi w myślach :)

a punkt odniesienia i moje nieśmiałem próbki w Action! tutaj:
http://tooloudtoowide.marcinrusinowski. … vs-action/

Ostatnio edytowany przez tooloudtoowide (2020-01-24 13:45:02)

/|\ 800 Incognito+Supercard - 800XL - 1088XEL CF3 - XE GS Ultimate VBXE - SIO2SD - SIDE2 - CA2001 - 1050 - XF551 clone by Zaxon /|\ PORTFOLIO

7

Odp: wydajnościówka w Action!

TDC po 30 latach dokonał wiekopomnego odkrycia a ja to opisałem rok temu w poście 48 https://atarionline.pl/forum/comments.p … e=1#Item_0 po 2-mc zabawy ;)

DEFINE
  RBARON="[$A9$E$8D$D40A$8D$D01A]",RBAROFF="[$A9$0$8D$D01A]"

BYTE ARRAY MATRIX=0
BYTE ARRAY MEMMATRIX(21)

CARD
  MEMADDR=$CA

BYTE
  I=$CC

PROC RSYNC=*(BYTE L)[$CD$0B$D4$D0$FB$60]

PROC OLDSTUFF=*()
  FOR I=0 TO 20 DO
    MATRIX(MEMADDR)=255
    MEMADDR==+1
  OD
RETURN

PROC NEWSTUFF=*()
  FOR I=0 TO 20 DO
    MEMMATRIX(I)=255
  OD
RETURN

PROC MAIN=*()

  MEMMATRIX^=$9000

  DO
    MEMADDR=$9000
    RSYNC(40)
    RBARON OLDSTUFF() RBAROFF

    RSYNC(80)
    RBARON NEWSTUFF() RBAROFF
  OD

RETURN

Ostatnio edytowany przez zbyti (2021-04-25 23:42:05)

Post's attachments

atari000.png 1.34 kb, nikt jeszcze nie pobierał tego pliku. 

Tylko zalogowani mogą pobierać załączniki.

8

Odp: wydajnościówka w Action!

Oj, coś mi tu śmierdzi wojną polsko-polską a nie wojenka A8 i C= :-)

https://systemembedded.eu/
""Ja bardzo przepraszam, ale podejrzenia panów są całkowicie bezpodstawne. Ja niczym nie handluję. Ta pani przyszła do mnie w tym Pancake-u i w nim wychodzi.""
ABBUC Member #319. Preferowana forma kontaktu: email

9

Odp: wydajnościówka w Action!

A gdzie tam... Skoro ten trick jest taki wiekopomny a TDC ociąga się z jego udokumentowaniem to "na każdym zebraniu jest taka sytuacja, że ktoś musi zacząć pierwszy". :D

Ostatnio edytowany przez zbyti (2021-04-26 08:49:52)

10

Odp: wydajnościówka w Action!

boje sie zapytac... ktos zauwazyl roznice miedzy trybem indeksowanym i posrednim indeksowanym? bo jesli tak czekam na odkrycie operacji dodawania.

http://atari.pl/hsc/ad.php?i=1.

11

Odp: wydajnościówka w Action!

@xxl

OLDSTUFF()

0E25: A0 00     LDY #$00
0E27: 84 CC     STY $CC
0E29: A9 14     LDA #$14
0E2B: C5 CC     CMP $CC
0E2D: B0 03     BCS $0E32
0E2F: 4C 52 0E  JMP $0E52
0E32: 18        CLC
0E33: AD 08 0E  LDA $0E08
0E36: 65 CA     ADC $CA     ;LOADFLG
0E38: 85 AE     STA $AE     ;LELNUM+1
0E3A: AD 09 0E  LDA $0E09
0E3D: 65 CB     ADC $CB
0E3F: 85 AF     STA $AF     ;STENUM
0E41: A9 FF     LDA #$FF
0E43: A0 00     LDY #$00
0E45: 91 AE     STA ($AE),Y ;LELNUM+1
0E47: E6 CA     INC $CA     ;LOADFLG
0E49: D0 02     BNE $0E4D
0E4B: E6 CB     INC $CB
0E4D: E6 CC     INC $CC
0E4F: 4C 29 0E  JMP $0E29
0E52: 60        RTS

NEWSTUFF()

0E53: A0 00     LDY #$00
0E55: 84 CC     STY $CC
0E57: A9 14     LDA #$14
0E59: C5 CC     CMP $CC
0E5B: B0 03     BCS $0E60
0E5D: 4C 6C 0E  JMP $0E6C
0E60: A9 FF     LDA #$FF
0E62: A6 CC     LDX $CC
0E64: 9D 0A 0E  STA $0E0A,X
0E67: E6 CC     INC $CC
0E69: 4C 57 0E  JMP $0E57
0E6C: 60        RTS

Trzeba by przykład w Action! dopracować, ale nie będę na to czasu poświęcał bo dokładnie o to chodzi.

MEMMATRIX^=$9000

Nie pisałem już dawno w Action! na to miałem jakieś obejście ale już nie pamiętam, po prostu jak się to zrobi tak by strzelało w $9000 to dokładnie chodzi o to co piszesz.

Ostatnio edytowany przez zbyti (2021-04-26 09:51:07)

12

Odp: wydajnościówka w Action!

jak sie czyta zrodla co on generuje... nie da sie uratowac tego kompilatora

http://atari.pl/hsc/ad.php?i=1.

13

Odp: wydajnościówka w Action!

Już wiem:

SET $E=$2000 SET $491=$2000

DEFINE
  RBARON="[$A9$E$8D$D40A$8D$D01A]",RBAROFF="[$A9$0$8D$D01A]"

BYTE ARRAY MATRIX=0
BYTE ARRAY MEMMATRIX(21)=$9000

CARD
  MEMADDR=$CA

BYTE
  I=$CC

PROC RSYNC=*(BYTE L)[$CD$0B$D4$D0$FB$60]

PROC OLDSTUFF=*()
  FOR I=0 TO 20 DO
    MATRIX(MEMADDR)=255
    MEMADDR==+1
  OD
RETURN

PROC NEWSTUFF=*()
  FOR I=0 TO 20 DO
    MEMMATRIX(I)=255
  OD
RETURN

PROC MAIN=*()

  DO
    MEMADDR=$9000
    RSYNC(40)
    RBARON OLDSTUFF() RBAROFF

    RSYNC(80)
    RBARON NEWSTUFF() RBAROFF
  OD

RETURN

------------

BYTE ARRAY MEMMATRIX(21)=$9000
PROC NEWSTUFF=*()
  FOR I=0 TO 20 DO
    MEMMATRIX(I)=255
  OD
RETURN
2036: A0 00     LDY #$00
2038: 84 CC     STY $CC
203A: A9 14     LDA #$14
203C: C5 CC     CMP $CC
203E: B0 03     BCS $2043
2040: 4C 4F 20  JMP $204F
2043: A9 FF     LDA #$FF
2045: A6 CC     LDX $CC
2047: 9D 00 90  STA $9000,X
204A: E6 CC     INC $CC
204C: 4C 3A 20  JMP $203A
204F: 60        RTS

14

Odp: wydajnościówka w Action!

Język wysokiego poziomu (ACTION!) powstał aby skrócić pisanie programów. To co robisz jest w procedurach bibliotecznych języka. Z ciekawości dołączyłem do twojego testu taką procedurę żeby sprawdzić ile zajmuje czasu.
Jeżeli jest za długa, to jak widzę nieźle sobie radzisz z wstawkami maszynowymi i na pewno możesz napisać własną.


SET $E=$2000 SET $491=$2000

DEFINE
  RBARON="[$A9$E$8D$D40A$8D$D01A]",RBAROFF="[$A9$0$8D$D01A]"

BYTE ARRAY MATRIX=0
BYTE ARRAY MEMMATRIX(21)=$9000

CARD
  MEMADDR=$CA

BYTE
  I=$CC

PROC RSYNC=*(BYTE L)[$CD$0B$D4$D0$FB$60]

PROC OLDSTUFF=*()
  FOR I=0 TO 20 DO
    MATRIX(MEMADDR)=255
    MEMADDR==+1
  OD
RETURN

PROC NEWSTUFF=*()
  FOR I=0 TO 20 DO
    MEMMATRIX(I)=255
  OD
RETURN

PROC MAIN=*()

  DO
    MEMADDR=$9000
    RSYNC(40)
    RBARON OLDSTUFF() RBAROFF

    RSYNC(80)
    RBARON NEWSTUFF() RBAROFF

    RSYNC(100)
    RBARON
    SETBLOCK(MEMMATRIX,20,255)
    RBAROFF
  OD  

RETURN

PS.
Życzę dużo satysfakcji w poznawaniu 8-bitowców, powodzenia w budowie i tworzeniu gier.

15

Odp: wydajnościówka w Action!

supaplex napisał/a:

To co robisz jest w procedurach bibliotecznych języka.

Ja ich celowo nie używam lub dołączam jako własny runtime aby po zapisaniu programu do XEX nie był potrzebny cartridge Action! w komputerze.

Do tego napisałem tak jak napisałem bo to narzucił artykuł TDC https://tdc-smakowitosci.blogspot.com/2 … ction.html

TDC napisał/a:

Korzystaliśmy z tego rozwiązania latami, będąc przekonanymi, że nie ma w żadnym języku czegoś szybszego i bardziej sprytnego;)

(...)

Okazało się, że myk jaki wymyśliłem - Action! kompiluje do 5 bajtów kodu dla stałej i do 8 bajtów przy zmiennym adresie (animacji). Jest to najmniejszy rozmiar kodu jaki da się wygenerować, więc krócej i szybciej na Atari się już nie da;))

Coś niesamowitego, naprawdę sądziłem przez kilkadziesiąt lat, że szybciej się już nie da... A jednak!;)

Sednem tego artykułu nie jest wypełnienie pamięci jakąś jedną wartością tylko wymuszenie szybkiego trybu indeksowego. TDC SETBLOCK używa od zawsze, nie o to chodzi.

Jak pokazałem rok temu na AOL ta metoda pozwala także na osiągnięcie upragnionego LDA/STA w miejsce PEEK i POKE.

---

TDC napisał/a:

Wrato zaznaczyć, że do dziś wszyscy pamiętają, że Action! to znaczy szybkość i że nie ma możliwości odnalezienia innego języka, który byłby prawie tak szybki jak asembler.

xxl napisał/a:

jak sie czyta zrodla co on generuje... nie da sie uratowac tego kompilatora

Ostatnio edytowany przez zbyti (2021-04-27 13:13:45)

16

Odp: wydajnościówka w Action!

Widzę, że Tomek nie odpuszcza i wyzwanie wciąż "aktualne" ;)

Widocznie przedstawienie przeze mnie idei (i sposobu jak to osiągnąć w Action!), którą praktycznie od razu odgadł Ilmenit patrząc na raster time nie wystarczy.

Ilmenit napisał/a:

3. Nie patrzyłem w wynikowy kod, ale twoje "odkrycie" to prawdopodobnie wygenerowanie dostępu do tablicy w trybie adresowania "Absolute Indexed", co wcześniej nie działało, ponieważ inkrementowałeś dwubajtowy wskaźnik a teraz masz stałą. Zakładam, że podobny efekt można uzyskać w wielu kompilatorach z tamtego okresu, bo nie ma powodu, aby nie można było.

Może trzeba podać dokładne rozwiązanie?

BYTE ARRAY FastP(0)=$9000

Tak, każdy wie, że Action! nie pilnuje zakresu tablic :]

Na podstawie snippetów z wpisu TDC na blogu obaj mamy szybką tablicę bajtów, obaj mamy takie same raster time dla tego kodu ale Tomek to robi inaczej?

Ostatnio edytowany przez zbyti (2021-04-27 23:39:40)

17

Odp: wydajnościówka w Action!

TeDeC tu nie pisze już.

18

Odp: wydajnościówka w Action!

@AS... doskonale o tym wiem, ale stosuję erystyczną sztuczkę "gadki pod publiczkę" ;)

Ja jestem z tych sofistów co otwarcie mówią jakie metody stosują, tyle, że ja dążę do prawdy a nie do tego by moje było na wierzchu :]

--- ed ---

TDC napisał, że zawstydziłem Ilmenita. Ja osobiście nie bardzo wiem gdzie. Jeżeli ktoś byłby łaskaw przykleić moje stanowisko na forum AOL to brzmi ono:

zbyti napisał/a:

TDC przestań robić wyzwania programistyczne w Action! Ilmenitowi. Dla każdego znającego jego osiągnięcia jest jasne, że gdyby Ilmenit uznał to za istotne to zmusił by kompilator Action! do prania jego starych gaci w rzece i jednoczesnego śpiewania przy tym międzynarodówki :]

Ostatnio edytowany przez zbyti (2021-04-28 09:57:32)