Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - Zum C-Control-I-Forum - Zum C-Control-II-Forum

Re: Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte Kategorie: Programmierung Basic (von PeterS - 1.11.2010 11:43)
Als Antwort auf Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte von Ernst H. - 30.10.2010 14:08

Hallo Ernst,

jetzt arbeite ich schon an einem Feiertag damit Deine plakativen Ã?uÃ?erungen und Dein
fehlerhafter Benchmark nicht unwidersprochen im Raum stehenbleiben.

Der Fehler im Benchmark ist, das die Generierung von Debugcode im Test eingeschaltet
blieb, so wurden Bytecodes mitgemessen die zum SingleStep im Debugger dienen. Die neuen
Benchmarkergebnisse und den überarbeiteten Benchmark habe ich unten angefügt. Die neuen
Ergebnisse zeigen, das die alten Werte bis zu 40% (bei ++Var) zu hoch gemessen wurden.

Zu Deiner Aussage "Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte",
sorry Ernst, aber das ist Bild-Zeitungsniveau. Du kannst nicht eine Float Multiplikation
mit einer Word Multiplikation plus Division vergleichen, ohne darauf hinzuweisen, das es
hier um einen Spezialfall einer Berechnung gilt. Wenn ich solche allgemeinen Schlagzeilen
heraushaue, dann muÃ? ich die gleichen Berechnungen vergleichen. Hier Word Multiplikation
plus Division = 649 Takte zu Single Mutliplikation plus Division = 1892 Takte, und da habe
ich einen Unterschied von Faktor 3!

Word Mult:          303
Word Mult + Div:    649
Single Mult:        920
Single Mult + Div:  1892


Zu Deinem Problem mit "++Var" und "Var=Var+1". In den neuen Benchmarkergebnissen sieht man, das
"++Var" = 185 Takte deutlich schneller als "Var=Var+1" = 260 Takte ist. Was Du nicht wissen
kannst, ist das "++Var" ineffizienter ist, wenn man den Wert von Var vom Stack verwirft, also
nicht z.B. "Var2= ++Var" = 206 Takte schreibt. Dies ist deutlich effizienter als ein "Var2= Var"
und "Var=Var+1" mit insgesamt 395 Takten.

++Var:       185
Var=Var+1:   260
Var2= ++Var: 206
"Var2= Var" und "Var=Var+1": 395


Wie ich schon geschrieben habe, habe ich einen Overhead von 36 Takten, die für das Fetch Bytecode,
Table lookup, Sprung in den Bytecode drauf gehen. Inklusive ist Management von Interrupts und
Multitasking. Dieses Performance Problem haben alle Interpreter. Wegen der Harvard Architektur
schneidet der Atmel Mega darin noch ein wenig schlechter ab, als z.B. eine 32-Bit x86 Architektur.



Korrekte Benchmark Messwerte:
-----------------------------

Mess1  ++Var (Byte)         Takte= 185 12.543000us  
Mess2 Var=Var+1 (Byte)      Takte= 260 17.628000us  
Mess3 2xPort_WriteBit       Takte= 886 60.070800us  
Mess4 2xPort_WriteBit ++Var Takte= 1071 72.613800us
Mess5 Port_Write            Takte= 366 24.814800us  
Mess6 DirAcc_Write          Takte= 359 24.340200us  
Mess7  PortBit Eigenbau     Takte= 573 38.849399us  
Mess8 Port_WriteBit         Takte= 443 30.035400us  
Mess9 Schleife 10000        N128= 3782 32.827758ms  
Mess10 ULong=ULong+1        Takte= 409 27.730199us  
Mess11 ULong vergleich      Takte= 563 38.171401us  
Mess12 Byte Vergleich       Takte= 297 20.136600us  
Mess13 ADC abfrage          Takte= 2265 153.567001us
Mess14 Case   abfrage       Takte= 756 51.256801us  
Mess15 If  abfrage          Takte= 1855 125.768997us
Mess16 ADC abfrage 8x       Takte= 18375 1245.824951us
Mess17 Floatberech          Takte= 920 62.375999us
Mess18 Word Mul/Div 2Komma  Takte= 649 44.002201us


Ã?berarbeiteter Benchmark:
-------------------------

'Fertiges Programm zum Ausgeben von Messungen -einfach starten-
'Ergebnis erscheint an Konsole

Dim Zeitfloat As Single
Dim Timervar As Word
Dim Var As Byte         ' für Tests Nr1 ++Var, und Var=Var+1
Dim Var2 As Byte
Dim i As Integer        ' For Schleife
Dim Schleife As Integer
Dim Longvar As ULong
Dim Longvar2 As ULong
Dim Pausenzeit As Word
Dim ADC_0 As Word
Dim Wordvar As Word
Dim Floatvar As Single
Dim txt(60) As Char

#define Pausenzeit 1000    '2sec Pause zwischen den Messungen
#define Duchlaufe 3
#define Ref 0.004887          'Referenzspannungsfaktor für ADC - Test




Sub main()
 Do While (1)
  Port_DataDir(PortC,255 )    'PortC alles Output.. zum Messen

  Msg_WriteText("Mess1  ++Var (Byte)        " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
                        'bei 65000 wird Int ausgelöst, hier nicht verwendet
         ++Var       'hier die Prüf - Anweisungen oder ganze Programmteile
                        'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
    Msg_WriteChar(13)   'CR  ... Neue Zeile
    AbsDelay(Pausenzeit )  'Zeit zum ablesen

        'nun Test2:

  Msg_WriteText("Mess2 Var=Var+1 (Byte)     " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
        Var=Var+1    'hier die Prüf - Anweisungen oder ganze Programmteile
                     'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1()  ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen

        'nun Test3:


  Msg_WriteText("Mess3 2xPort_WriteBit      " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
      Port_WriteBit(20,1) 'hier die Prüf - Anweisungen oder ganze Programmt.
      Port_WriteBit(20,0) 'PortC.4 auf 0
                          'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1()   ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen

        'nun Test4:
  Msg_WriteText("Mess4 2xPort_WriteBit ++Var" )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
      Port_WriteBit(20,1) 'hier die Prüf - Anweisungen oder ganze Programmt.
        ++Var            'mit Logkanalyser können die zusätzlichen 260Takte..
      Port_WriteBit(20,0)
                        'bis max 4,4ms  67,8ns Takt = 14,..MHz
      Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen


       'nun Test5:
  Msg_WriteText("Mess5 Port_Write           " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
    Port_Write(PortC,255 ) 'hier die Prüf - Anweisungen oder ganze Programmt.
                                 'bis max 4,4ms  67,8ns Takt = 14,7456MHz
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen

        'nun Test6:
  Msg_WriteText("Mess6 DirAcc_Write         " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)   ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
    DirAcc_Write(0x35,255 ) 'hier die Prüf - Anweisungen oder ganze Progr.
                            'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1()         ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen


      'nun Test7:
  Msg_WriteText("Mess7  PortBit Eigenbau    " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
      DirAcc_Write(0x35,DirAcc_Read(0x35 Or 00010000 ) )
           'das PortC Register wird gelesen maskiert und damit Bit 4 gesetzt
                    'hier die Prüf - Anweisungen oder ganze Programmteile
                                 'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen


    'nun Test8:
  Msg_WriteText("Mess8 Port_WriteBit        " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
      Port_WriteBit(20,1) 'hier die Prüf - Anweisungen oder ganze Programmt.
                                'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen


        'nun Test9:      hier langsamerer Takt: 8,68us
  Msg_WriteText("Mess9 Schleife 10000       " )
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,5)   ' Startpunkt der Messung mit 8,68usTakt
      For Schleife = 1 To 10000'hier die Prüf - Anweisungen oder ganze Progr.
             ++Var
      Next                      'bis zu 0,56sec
    Msg_Laufzeit128T() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen


    'nun Test10:
  Msg_WriteText("Mess10 ULong=ULong+1      " )
  Longvar = 4294967294     ' damit in 2. Durchlauf ein Ã?berlauf entsteht
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
            'hier die Prüf - Anweisungen oder ganze Programmteile
    Longvar = Longvar + 1       'bis max 4,4ms  67,8ns Takt = 14,..MHz
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen


  'nun Test11:
  Msg_WriteText("Mess11 ULong vergleich    " )
  Longvar = 4294967000     '
  Longvar = 4294967010     'eine hohe Zahl - es müssen alle 32 Bits vergl.
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
    If Longvar2 < Longvar Then      'bis max 4,4ms  67,8ns Takt = 14,..MHz
        ++Var     ' hier vergleich nicht erfüllt, Var bleibt gleich
    End If
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen




  'nun Test12:
  Msg_WriteText("Mess12 Byte Vergleich     " )
  Var = 222     '
  Var2 = 243     '
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
    If Var2 < Var Then      'bis max 4,4ms  67,8ns Takt = 14,..MHz
        ++Var     ' hier vergleich nicht erfüllt, Var bleibt gleich
    End If
    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen



 'nun Test13:
  Msg_WriteText("Mess13 ADC abfrage        " )    '
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
      ADC_Set(ADC_VREF_VCC,0)
      ADC_0 = ADC_Read()

 'Takte= 4008 271.742401us  Takte= 2397 162.516601us  Takte= 2382 161.49..
 'beim ersten Aufruf 4008, dann nurmehr ca 2380

    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen

     'nun Test14:
  Msg_WriteText("Mess14 Case   abfrage     " )     '
  Var=5
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
      Select Case Var
        Case 1
            ++Var2
        Case 2
            ++Var2
        Case 3
            ++Var2
        Case 4
            ++Var2
        Case 5
            ++Var2
        Case 6
            ++Var2
      End Select

    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen



   'nun Test15:
  Msg_WriteText("Mess15 If  abfrage        " )     '
  Var=5
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
      If Var = 1 Then
            ++Var2
      End If
      If Var = 2 Then
            ++Var2
      End If
      If Var = 3 Then
            ++Var2
      End If
      If Var = 4 Then
            ++Var2
      End If
      If Var = 5 Then
            ++Var2
      End If
      If Var = 6 Then
            ++Var2
      End If
      'ist nicht exakt mit obiger Case vergleichbar, aber ähnlich

  Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen

  'nun Test16:
  Msg_WriteText("Mess16 ADC abfrage 8x     " )    '
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
      ADC_Set(ADC_VREF_VCC,0)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,1)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,2)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,3)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,4)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,5)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,6)
      ADC_0 = ADC_Read()
      ADC_Set(ADC_VREF_VCC,7)
      ADC_0 = ADC_Read()


    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen



     'nun Test17:
  Msg_WriteText("Mess17 Floatberech        " )     '
  Wordvar=1023
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile
            Floatvar = Wordvar * Ref
      'Mess17 Floatberech   Takte= 995 67.460998us  Takte= 995 67.460998us

    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next
  Msg_WriteText("U=")
  Msg_WriteFloat(Floatvar)
  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen



     'nun Test18:
  Msg_WriteText("Mess18 Word Mul/Div 2Komma" )     '
  Wordvar=1023
  For i = 1 To Duchlaufe             'für 3-malige Ausgabe in einer Zeile
    AbsDelay(2 ) ' unbedingt notwendig!!!  nur mit 2ms Pause konstante Werte
    Timer_T1Time(65000,1)  ' Startpunkt der Messung 67,8ns Takt Cnt1 = 0
          'hier die Prüf - Anweisungen oder ganze Programmteile

        ADC_0 = Wordvar * 64 /131
  'Mess18 Word Mul/Div 2Komma Takte= 724 49.087200us  Takte= 724 49.087200us

    Msg_Laufzeit1() ' Aufruf der Sub (Cnt Auslesung und Korrektur)
  Next

  Msg_WriteText("U=")
  Msg_WriteWord(ADC_0 )

  Msg_WriteChar(13)   'CR  ... Neue Zeile
  AbsDelay(Pausenzeit )  'Zeit zum ablesen

  Msg_WriteChar(13)   'CR  ... Neue Zeile  letzte Zusatzzeile
 End While
End Sub  'main  ************************************

Sub Msg_Laufzeit1 ()                      ' Sub für Messung und Ausgabe
    Timervar = Timer_T1GetCNT() - 230     ' Korr-Wert wenn kein Befehle
    Str_Printf(txt, " Takte= %d %fus ", Timervar, Timervar * 0.0678)
    Msg_WriteText(txt)
End Sub

Sub Msg_Laufzeit128T ()    ' nur mit 2ms Pause am Beginn konstante Werte !!
    Schleife = Schleife + 1 - 1  ' Zeitverbrauch damit wenige Takte abgezogen
    Timervar = Timer_T1GetCNT() - 1       ' Korrektur -1
    Str_Printf(txt, " N128= %d %fms ", Timervar, Timervar * 0.00868)
    Msg_WriteText(txt)
End Sub



    Antwort schreiben


Antworten:

Re: Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte (von Ernst - 2.11.2010 19:45)
    Re: Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte (von PeterS - 3.11.2010 9:50)
        Re: Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte (von ThomasK - 15.10.2012 22:57)
            Re: Berechnung mit Word anstelle Single bringt fast nichts 995 zu 724 Takte (von PeterS - 16.10.2012 10:46)