Delphi-PRAXiS
Seite 13 von 16   « Erste     3111213 1415     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Anzahl eines Zeichens im String ermitteln (https://www.delphipraxis.net/116372-anzahl-eines-zeichens-im-string-ermitteln.html)

KodeZwerg 14. Jul 2018 23:01

AW: Anzahl eines Zeichens im String ermitteln
 
Hier schau mal selbst, das ist mit nur 50000 Zeichen/Bytes, achte auf den Ydobon Zeitwert. Katastrophal bei mir.
Diese Ergebnisse sind nicht unter optimalen Voraussetzungen entstanden da alle Kerne mit was anderem ausgelastet sind.
Zitat:

KodeZwerg's custom Benchmark - DP CountCharInString Edition

Benchmark: Sleep(500)
501037 Nanoseconds wasted. As closer this is to 500000 more accurate Results are given.

Benchmark: Generate Random Data String (50000 chars) Charset: [aA0-zZ9]
609 Nanoseconds wasted.

Benchmark: 1234588 miep(Data, 'X')
141 Nanoseconds wasted. (found X = 748 times)

Benchmark: Ydobon Length(Data)-Length(StringReplace(Data, 'X', '', [rfReplaceAll]))
21149 Nanoseconds wasted. (found X = 748 times)

Benchmark: marabu Occurs(Data, 'X')
201 Nanoseconds wasted. (found X = 748 times)

Benchmark: Missionar cCount(Data, 'X')
139 Nanoseconds wasted. (found X = 748 times)

Benchmark: alzaimar IFCount(Data, 'X')
122 Nanoseconds wasted. (found X = 748 times)

Benchmark: Uwe Raabe StringCountChar(Data, 'X')
122 Nanoseconds wasted. (found X = 748 times)

Benchmark: KodeZwerg CountCharInString(Data, 'X')
160 Nanoseconds wasted. (found X = 748 times)

Benchmark: KodeZwerg CharInStringA(Data, 'X')
253 Nanoseconds wasted. (found X = 748 times)

Benchmark: Uwe Raabe CharCount(Data, 'X')
89 Nanoseconds wasted. (found X = 748 times)

Benchmark: Uwe Raabe CharCount2(Data, 'X')
58 Nanoseconds wasted. (found X = 748 times)

Benchmark: EgonHugeist CharCount3(Data, 'X')
74 Nanoseconds wasted. (found X = 748 times)

Benchmark: Neutral General CharCountAsm(Data, 'X', Length(Data))
115 Nanoseconds wasted. (found X = 748 times)

Benchmark: EgonHugeist EH_CharCount4(Data, 'X')
76 Nanoseconds wasted. (found X = 748 times)

Benchmark: StrScanFast(Data, 'X')
1 Nanoseconds wasted. (found X = 49895 times)

Benchmark: Generate Random Binary Data String (50000 bytes)
324 Nanoseconds wasted.

Benchmark: 1234588 miep(Data, 'X')
109 Nanoseconds wasted. (found X = 180 times)

Benchmark: Ydobon Length(Data)-Length(StringReplace(Data, 'X', '', [rfReplaceAll]))
5814 Nanoseconds wasted. (found X = 180 times)

Benchmark: marabu Occurs(Data, 'X')
204 Nanoseconds wasted. (found X = 180 times)

Benchmark: Missionar cCount(Data, 'X')
131 Nanoseconds wasted. (found X = 180 times)

Benchmark: alzaimar IFCount(Data, 'X')
108 Nanoseconds wasted. (found X = 180 times)

Benchmark: Uwe Raabe StringCountChar(Data, 'X')
109 Nanoseconds wasted. (found X = 180 times)

Benchmark: KodeZwerg CountCharInString(Data, 'X')
1 Nanoseconds wasted. (found X = 1 times)

Benchmark: KodeZwerg CharInStringA(Data, 'X')
71 Nanoseconds wasted. (found X = 1 times)

Benchmark: Uwe Raabe CharCount(Data, 'X')
1 Nanoseconds wasted. (found X = 1 times)

Benchmark: Uwe Raabe CharCount2(Data, 'X')
63 Nanoseconds wasted. (found X = 180 times)

Benchmark: EgonHugeist CharCount3(Data, 'X')
59 Nanoseconds wasted. (found X = 180 times)

Benchmark: Neutral General CharCountAsm(Data, 'X', Length(Data))
154 Nanoseconds wasted. (found X = 180 times)

Benchmark: EgonHugeist EH_CharCount4(Data, 'X')
67 Nanoseconds wasted. (found X = 180 times)

Benchmark: StrScanFast(Data, 'X')
1 Nanoseconds wasted. (found X = 75 times)

jaenicke 14. Jul 2018 23:50

AW: Anzahl eines Zeichens im String ermitteln
 
Delphi 2009 war ja die erste Version mit Unicode. Vermutlich war dort die Umsetzung von StringReplace schlicht noch nicht so gut.

KodeZwerg 15. Jul 2018 01:01

AW: Anzahl eines Zeichens im String ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Anhang 49520So in etwa würde neue GUI aussehen.
Wem noch mehr sinnvolle Optionen einfallen, bitte melden.

Edit
Ps: Ein Cancel Button ist nun vorhanden :)

KodeZwerg 15. Jul 2018 01:41

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von jbg (Beitrag 1407285)
Dann möchte ich meine schnell zusammengeschrieben Assembler-Rountine auch noch ins Rennen werfen.

Delphi 2009 verweigert mir Deinen Code. Benötige ich dafür ein aktuelleres Delphi als 2009 oder fehlt mir was in Uses?
Delphi-Quellcode:
Windows, SysUtils;
habe ich momentan drinnen.
Zitat:

[DCC Error] uCharInString.pas(277): E2003 Undeclared identifier: 'rdi'
[DCC Error] uCharInString.pas(337): E2003 Undeclared identifier: 'rcx'
[DCC Error] uCharInString.pas(340): E2003 Undeclared identifier: 'r8'
[DCC Error] uCharInString.pas(341): E2003 Undeclared identifier: 'rax'
[DCC Error] uCharInString.pas(346): E2003 Undeclared identifier: 'movsxd'
[DCC Error] uCharInString.pas(349): E2003 Undeclared identifier: 'r9'

himitsu 15. Jul 2018 01:59

AW: Anzahl eines Zeichens im String ermitteln
 
Wollt ihr den String nicht auch noch aufteilen und Multithreaded mit SSE/MMX/... oder besser noch mit CUDA/OpenCL/... beackern?


Zitat:

[DCC Error] uCharInString.pas(277): E2003 Undeclared identifier: 'rdi'
[DCC Error] uCharInString.pas(337): E2003 Undeclared identifier: 'rcx'
[DCC Error] uCharInString.pas(340): E2003 Undeclared identifier: 'r8'
[DCC Error] uCharInString.pas(341): E2003 Undeclared identifier: 'rax'
[DCC Error] uCharInString.pas(346): E2003 Undeclared identifier: 'movsxd'
[DCC Error] uCharInString.pas(349): E2003 Undeclared identifier: 'r9'
2009 und 64 Bit :stupid::roll:

himitsu 15. Jul 2018 02:08

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von KodeZwerg (Beitrag 1407305)
Zitat:

Zitat von jbg (Beitrag 1407285)
Dann möchte ich meine schnell zusammengeschrieben Assembler-Rountine auch noch ins Rennen werfen.

Delphi 2009 verweigert mir Deinen Code. Benötige ich dafür ein aktuelleres Delphi als 2009 oder fehlt mir was in Uses?
Delphi-Quellcode:
Windows, SysUtils;
habe ich momentan drinnen.
Zitat:

[DCC Error] uCharInString.pas(277): E2003 Undeclared identifier: 'rdi'
[DCC Error] uCharInString.pas(337): E2003 Undeclared identifier: 'rcx'
[DCC Error] uCharInString.pas(340): E2003 Undeclared identifier: 'r8'
[DCC Error] uCharInString.pas(341): E2003 Undeclared identifier: 'rax'
[DCC Error] uCharInString.pas(346): E2003 Undeclared identifier: 'movsxd'
[DCC Error] uCharInString.pas(349): E2003 Undeclared identifier: 'r9'




PS: Wer viel misst misst Mist.
Gerade beim Selbstbau von Assemblerzeugs sollte man auch beachten, dass CPUs sich unterschiedlich verhalten.
Einige halbwegs Aktuelle planen z.B. schonmal vor und werden dann ausgebremst, wenn der Code sich anders/unvorhersehbar/abwechselnd verhält.
Ich hatte mal eine Zählschleife gebaut und bremste meine CPU so aus, dass die For-In-Schleife von Delphi doppelt so schnell lief. :stupid:

KodeZwerg 15. Jul 2018 05:55

AW: Anzahl eines Zeichens im String ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 2)
Anhang 49521 So sieht mein letzter Entwurf aus.
Vorkompiliert plus Source im Anhang.
Es sind noch nicht alle Varianten enthalten, aber bitte testet mal ob das einem Benchmark gerecht wird.

Abgesehen von noch fehlender Methoden brauche ich auch Hilfe bei etwas was mir gerade den Kopf verdreht.
Delphi-Quellcode:
 if ((Tests.ItemIndex = 0) or (Tests.ItemIndex = 1)) then
  begin
    for Loops := 0 to Times.Value do
    begin
      QueryPerformanceCounter(Int64((@lpPerformanceCount1)^));
      i := CharInString.miep(Data, Ch);
      QueryPerformanceCounter(Int64((@lpPerformanceCount2)^));
      QueryPerformanceFrequency(Int64((@Frequency)^));
      Curr := (1000000 * (lpPerformanceCount2.QuadPart - lpPerformanceCount1.QuadPart) / Frequency.QuadPart);
      if Loops = 0 then
      begin
        Last := Curr;
        Min := Curr;
        Max := Curr;
        Avg := Curr;
      end;
      if Curr < Min then Min := Curr;
      if Curr > Max then Max := Curr;
      if Curr < Last then Avg := (((Curr - Last) / 2) - Avg);
      if Curr > Last then Avg := (((Curr - Last) / 2) + Avg);
      Last := Curr;
      if fCancel = True then Break;
    end;
    Avg := Abs(Avg);
    if b = False then lstResults.Items.Add(format('%.10d',[Round(Avg)])+ ' - Statistic: [ASCII Data] ['+IntToStr(Round( Min + ((Max-Min)/2) ))+' Avg] ['+IntToStr(Round(Min))+' Min] ['+IntToStr(Round(Max))+' Max] [found ' + IntToStr(Ord(Ch)) + ' = '+IntToStr(i)+' times] @ Miep()');
    if b = True then lstResults.Items.Add(format('%.10d',[Round(Avg)])+ ' - Statistic: [Binary Data] ['+IntToStr(Round( Min + ((Max-Min)/2) ))+' Avg] ['+IntToStr(Round(Min))+' Min] ['+IntToStr(Round(Max))+' Max] [found ' + IntToStr(Ord(Ch)) + ' = '+IntToStr(i)+' times] @ Miep()');
  end;
  if fCancel = True then goto cancel;
So schaut nun ein kompletter Bench-Block aus, Hilfe brauche ich bei der Berechnung der Variable "Avg". Irgendwie mache ich da etwas falsch und komme gerade nicht auf die korrekte Lösung.
Die "Avg" Variable soll den praktischen Durchschnittswert darstellen wohingegen
Delphi-Quellcode:
['+IntToStr(Round( Min + ((Max-Min)/2) ))+' Avg]
den synthetischen Durchschnittswert darstellt.
Oder mache ich es bereits richtig? Mir dröhnt der Kopf. *Hilfe*

So hier sehen nun die Ergebnisse aus:
Zitat:

KodeZwerg's custom Benchmark - DP CountCharInString Edition

Benchmark: Sleep(500)
506229 Nanoseconds wasted. As closer this is to 500000 more accurate Results are given.

Benchmark: Generate Random Data String (500000 chars) Charset: [aA0-zZ9]
5977 Nanoseconds wasted.

0000000523 - Statistic: [ASCII Data] [645 Avg] [575 Min] [715 Max] [found 88 = 8068 times] @ Uwe Raabe CharCount2()
0000000764 - Statistic: [ASCII Data] [738 Avg] [724 Min] [751 Max] [found 88 = 8068 times] @ EgonHugeist EH_CharCount4()
0000000851 - Statistic: [ASCII Data] [667 Avg] [573 Min] [761 Max] [found 88 = 8068 times] @ EgonHugeist CharCount3()
0000000882 - Statistic: [ASCII Data] [602 Avg] [420 Min] [784 Max] [found 88 = 8068 times] @ EgonHugeist EH_CharCount_6()
0000001219 - Statistic: [ASCII Data] [1185 Avg] [1168 Min] [1202 Max] [found 88 = 8068 times] @ Uwe Raabe StringCountChar()
0000001222 - Statistic: [ASCII Data] [1107 Avg] [851 Min] [1363 Max] [found 88 = 8068 times] @ EgonHugeist EH_CharCount_5()
0000001352 - Statistic: [ASCII Data] [1165 Avg] [709 Min] [1620 Max] [found 88 = 8068 times] @ KodeZwerg CountCharInString()
0000001372 - Statistic: [ASCII Data] [1336 Avg] [1319 Min] [1354 Max] [found 88 = 8068 times] @ Uwe Raabe CharCount()
0000001517 - Statistic: [ASCII Data] [1426 Avg] [1161 Min] [1691 Max] [found 88 = 8068 times] @ Miep()
0000001559 - Statistic: [ASCII Data] [1423 Avg] [1168 Min] [1677 Max] [found 88 = 8068 times] @ alzaimar
0000001910 - Statistic: [ASCII Data] [1569 Avg] [1378 Min] [1760 Max] [found 88 = 8068 times] @ Missionar
0000002157 - Statistic: [ASCII Data] [1982 Avg] [1872 Min] [2092 Max] [found 88 = 8068 times] @ marabu
0000002400 - Statistic: [ASCII Data] [2062 Avg] [1889 Min] [2234 Max] [found 88 = 8068 times] @ KodeZwerg CharInStringA()
0000009962 - Statistic: [ASCII Data] [4643 Avg] [856 Min] [8430 Max] [found 88 = 8068 times] @ Neutral General CharCountAsm()
0012230425 - Statistic: [ASCII Data] [13141133 Avg] [12800203 Min] [13482064 Max] [found 88 = 8068 times] @ Ydobon
edit
Ps: Da es noch nicht Threaded kann man noch nicht Canceln !!!

jbg 15. Jul 2018 09:01

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von KodeZwerg (Beitrag 1407305)
Delphi 2009 verweigert mir Deinen Code. Benötige ich dafür ein aktuelleres Delphi als 2009 oder fehlt mir was in Uses?
Delphi-Quellcode:
Windows, SysUtils;
habe ich momentan drinnen.

Ach ja, da war doch was. Das CPUX86 DEFINE wurde ja erst später eingeführt, damit es mit dem CPUX64 harmoniert. Ersetze das
Delphi-Quellcode:
{$IFDEF CPUX86}
einfach durch ein
Delphi-Quellcode:
{$IFNDEF CPUX64}
(Das "N" nicht vergessen)

Uwe Raabe 15. Jul 2018 10:49

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von KodeZwerg (Beitrag 1407309)
So schaut nun ein kompletter Bench-Block aus,

Ich finde, du machst es dir hier unnötig kompliziert und erhöhst zumindest potentiell die Messungenauigkeit in dem du die Zeit für jede einzelne Iteration misst. In jedem Fall erhöhst du aber die Gesamtlaufzeit des Benchmarks (nicht das Ergebnis), weil innerhalb der Schleife ein Haufen berechnet wird (zur Zeit offenbar auch noch falsch), der da gar nicht nötig wäre (z.B. wird der von QueryPerformanceCounter gelieferte Wert bereits beim Windows-Start festgelegt).

Aktuell schaut deine Messung so aus:
Delphi-Quellcode:
      QueryPerformanceCounter(Int64((@lpPerformanceCount1)^));
      i := CharInString.miep(Data, Ch);
      QueryPerformanceCounter(Int64((@lpPerformanceCount2)^));
Die Auflösung von QueryPerformanceCounter liegt zwar unter 1 Mikrosekunde, aber deine Messungen liegen zum Teil deutlich unter diesem Wert. Das bedeutet, daß die gemessene Laufzeit im Bereich oder sogar unter der Messgenauigkeit liegt, was einen relativ hohen Messfehler, schlimmstenfalls sogar vollkommen unbrauchbare Ergebnisse erwarten lässt.

Diesen Messfehler kannst du sehr leicht reduzieren, wenn du die Messung über eine deutlich größere Anzahl der Aufrufe machst und dann durch diese Anzahl teilst. Die gemessene Zeit sollte also mindestens 2-3 Größenordnungen über der Messgenauigkeit liegen (das wären hier 0.01 - 0.1 ms).

Aktuell versuchst du die mehrfachen Einzelmessungen zu mitteln, was dir aber nur den Mittelwert der einzelnen Fehler liefert, diesen aber nicht zwingend verkleinert (z.B. wenn er immer positiv ist).

In meinem Benchmark hatte ich das schon so implementiert. Nach dem Start der Stopwatch wird die zu messende Funktion 10000x aufgerufen und dann die Gesamtzeit gemessen. Da hier nur die Rangfolge relevant ist, spare ich mir das Runterrechnen auf die mittlere Laufzeit eines einzelnen Aufrufs. Durch diese Maßnahme haben wir den obigen Messfehler auf 1/10000 verkleinert, womit er vernachlässigbar wird.

Nun kann man argumentieren, daß die Messung über die Schleife ja auch einen gewissen Overhead verursacht. Zu diesem Zweck mache ich einen Kalibrierungslauf mit der Fake-Funktion, die in Relation zu den später zu messenden Funktionen vernachlässigbar kurz ist. Die bisherigen Läufe ergaben alle eine vernachlässigbare Laufzeit der Timing-Schleife. Gegebenenfalls kann man den hier ermittelten Wert dann auch von den späteren Messergebnissen abziehen. Bei den 10000 Aufrufen liegt der Fehler deutlich unter 1/1000.

Übrigens: Wenn deine Delphi-Version noch keine TStopwatch kennt, es gibt eine offizielle und frei verfügbare Vorgängerversion von Allen Bauer: News Flash! Someone has already invented the wheel!

Harry Stahl 15. Jul 2018 11:31

AW: Anzahl eines Zeichens im String ermitteln
 
Zitat:

Zitat von KodeZwerg (Beitrag 1407303)
Anhang 49520So in etwa würde neue GUI aussehen.
Wem noch mehr sinnvolle Optionen einfallen, bitte melden.

Edit
Ps: Ein Cancel Button ist nun vorhanden :)

Wenn man die zu startenden Funktionen in einer Checklist-Box zuvor auswählen könnte, fände ich gut (evtl. über Popup-Menü mit Einträgen für alle abwählen und alle anwählen). Denn wenn man an einer Funktion evtl. selber noch was rumschrauben wollte, müsste man nicht alle Tests durchlaufen lassen...

Ansonsten::thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:21 Uhr.
Seite 13 von 16   « Erste     3111213 1415     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz