AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Anzahl eines Zeichens im String ermitteln
Thema durchsuchen
Ansicht
Themen-Optionen

Anzahl eines Zeichens im String ermitteln

Ein Thema von DevidEspenschied · begonnen am 27. Jun 2008 · letzter Beitrag vom 17. Jul 2018
Antwort Antwort
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Anzahl eines Zeichens im String ermitteln

  Alt 15. Jul 2018, 01:41
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? 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'
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.549 Beiträge
 
Delphi 12 Athens
 
#2

AW: Anzahl eines Zeichens im String ermitteln

  Alt 15. Jul 2018, 02:08
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? 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.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (15. Jul 2018 um 02:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Anzahl eines Zeichens im String ermitteln

  Alt 15. Jul 2018, 05:55
Screenshot - 15_07.jpg 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 ['+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 !!!
Angehängte Dateien
Dateityp: 7z Benchmark.7z (219,7 KB, 4x aufgerufen)
Gruß vom KodeZwerg

Geändert von KodeZwerg (15. Jul 2018 um 06:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.756 Beiträge
 
Delphi 12 Athens
 
#4

AW: Anzahl eines Zeichens im String ermitteln

  Alt 15. Jul 2018, 10:49
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!
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.485 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

AW: Anzahl eines Zeichens im String ermitteln

  Alt 15. Jul 2018, 09:01
Delphi 2009 verweigert mir Deinen Code. Benötige ich dafür ein aktuelleres Delphi als 2009 oder fehlt mir was in Uses? 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
{$IFDEF CPUX86} einfach durch ein {$IFNDEF CPUX64} (Das "N" nicht vergessen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:24 Uhr.
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