![]() |
Array SCHNELL auf Null setzen
was ist denn die schnellste Methode in Delphi ein dynmische Array
Delphi-Quellcode:
mit Nullen zu befüllen ?
Result = array of array of integer;
|
AW: Array SCHNELL auf Null setzen
Das
Delphi-Quellcode:
mit FillChar/ZeroMemory
array of integer
und das
Delphi-Quellcode:
mußt du dabei einzeln durchlaufen.
array of array
Ich weiß jetzt nicht genau, ob der Speicher beim Initialisieren mit 0 gef+llt wird, wenn ja, und wenn "schnell" = kurzer Code, dann eventuell auch so
Delphi-Quellcode:
A := nil;
SeltLength(A, L1, L2); |
AW: Array SCHNELL auf Null setzen
Beim Initialisieren wird das Array nicht mit Nullen gefüllt.
Delphi-Quellcode:
Wenn es wirklich auf Geschwindigkeit an kommt ist eine Struktur DynArray in DynArray aber nicht so optimal.
for n : = 0 to High(Result) do
if Length(Result[n]) > 0 then FillChar(Result[n][0], SizeOf(Result[n][0]) * Length(Result[n]), #0); |
AW: Array SCHNELL auf Null setzen
Zitat:
Delphi-Quellcode:
ruft intern
SetLength
Delphi-Quellcode:
aus System.pas auf. Dort steht dann (in XE7 Zeile 33931-33933) folgender Code:
DynArraySetLength
Delphi-Quellcode:
// Set the new memory to all zero bits
if newLength > oldLength then FillChar((PByte(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0); |
AW: Array SCHNELL auf Null setzen
Ist das 0-setzten eine dokumentierte Eigenschaft? Oder könnte das in zukünftigen Delphi-Versionen auch mal anders gelöst sein?
|
AW: Array SCHNELL auf Null setzen
Zitat:
Zitat:
|
AW: Array SCHNELL auf Null setzen
Dann sprechen wir von unterschiedlichen Delphi-Versionen, meine Hilfe sagt dazu:
Bei einer langen String- oder einer dynamischen Array-Variable weist SetLength dem in S referenzierten String oder Array die angegebene Länge zu. Dabei bleiben die Zeichen im String oder die Elemente im Array erhalten, jedoch ist der Inhalt des neu zugewiesenen Speicherbereichs nicht definiert. Eine Ausnahme stellt das Vergrößern der Länge von dynamischen Arrays dar, in dem die Elemente Typen sind, die initialisiert werden müssen (Strings, Varianten, Variant-Arrays oder Records, die solche Typen enthalten). Wenn S ein dynamisches Typen-Array ist, das initialisiert werden muss, wird der neu zugewiesene Platz auf 0 oder nil gesetzt. Das scheint aber nicht mehr zu stimmen, ob es aber garantiert werden kann, dass der Speicher in jedem Fall gelöscht wird? |
AW: Array SCHNELL auf Null setzen
Zitat:
Automatisch verwaltete Typen werden immer initialisiert, denn sonst könnten sie nicht autonatisch verwaltet werden. (von den entsprechenden Funktionen: SetLength, New, Create usw.,) Sowas Einfaches, wie z.B. Integer, Char, Record, statisches Array usw., wird per se nicht initialisiert, es sei denn es liegt in einem Bereich, welcher immer initialisiert wird. (z.B. globale Variablen oder als Felder in Klassen) Wie das nun beim Integer-Array aussieht, hab ich grade einfach nicht im Kopf. Vorallem ob das bei allen Delphi-Versionen und Plattformen auch gleich ist ... ansonsten kann man bei sich ja einfach mal im Code Nachsehen, oder das SetLength debuggen. |
AW: Array SCHNELL auf Null setzen
Zitat:
Um auf die Originalfrage zurückzukommen: Himitsu's Vorschlag mit dem erweiterten SetLength ist die schnellste Möglichkeit. |
AW: Array SCHNELL auf Null setzen
was vllt auch noch erwähnt werden sollte:
bei größeren Arrays könnte es sich lohnen, dies ggf. mittels move umzusetzen, die greift per assembler auf mov zu, könnte noch mal einen Speed-Schub geben. Hat nat. zur Voraussetzung, dass man irgendwo vorher einen Speicherbereich 0en hat und wird wohl auch nur dann sinnvoll, wenn mehr als ein mal aufgerufen wird (weil der initiale Bereich ja auch gefüllt werden muss, oder man findet vllt trickreich schon einen existierenden ;-) ). Denk ich jetzt mal so. |
AW: Array SCHNELL auf Null setzen
Also wie sieht denn nun der Code aus, um ein
Delphi-Quellcode:
zu füllen?
array of array of integer
Spontan:
Delphi-Quellcode:
Optimierungsvorschläge?
Procedure ZeroDynamicMatrix (aMatrix : TMatrix; rows, cols : Integer);
var i : Integer; NumberOfBytesPerRow : Integer; Begin setLength(aMatrix,rows); NumberOfBytesPerRow := cols*sizeof(aMatrix[0][0]); // sollte gehen, da compile time constant. for i:=0 to cols-1 do begin setLength(aMatrix[i], cols); FillChar(aMatrix[i][0], NumberOfBytesPerRow); end; end; |
AW: Array SCHNELL auf Null setzen
Was man noch machen kann, wenn das Array immer „rechteckig“ ist, ist, kein Array of Array zu nehmen, sondern den ganzen Speicherbereich am Stück anzufordern, und dann den Index von Hand (bzw. über entsprechende Getter und Setter) auszurechnen.
Statt:
Delphi-Quellcode:
So:
var a: array of array of integer;
SetLength(a, rows); for i := 0 to rows - 1 do SetLength(a[i], cols);
Delphi-Quellcode:
a[y,x] im ersten Beispiel entspricht dann a[y*cols + x] im zweiten Beispiel. Dadurch spart man erstens die Pointer-Dereferenzierungen auf der ersten Ebene, und außerdem ist der Zugriff auf die Elemente cacheeffizienter, weil es zwischendrin keine Lücken gibt. Beim naiven Ansatz könnte der Speichermanager die Unterarrays sonstwohin verstreuen.
var a: array of integer;
SetLength(a, rows*cols); Außerdem kann man das ganze Array dann mit einem einzigen Aufruf von FillChar nullen und braucht dazu keine äußere Schleife mehr. |
AW: Array SCHNELL auf Null setzen
Nach meinem Kenntnisstand ist der Delphi-Compiler intelligent genug um gleichförmige Arrays zu erkennen.
Statt:
Code:
formuliert man
for i := 0 to rows - 1 do
SetLength(a[i], cols);
Code:
Edit 1: Sorry, ich habe übersehen, dass das ja schon in #2 stand.
SetLength(a, rows, cols);
Edit 2: Leider ist der Compiler anscheinend doch zu doof. :-( ich bin frustriert. Vielleicht hätte ich bei Assembler bleiben sollen... |
AW: Array SCHNELL auf Null setzen
Was soll daran doof sein? Ein gleichförmiges zweidimensionales Array ist numal kein eindimensionales Array, obwohl man es als solches implementieren kann.
Und dann auch nur so weit, wie ich sichergehen kann, dass man nicht noch nachträglich eine Dimension verändert (dynamisch und so...) |
AW: Array SCHNELL auf Null setzen
Zitat:
|
AW: Array SCHNELL auf Null setzen
@Stevie:
Vielleicht war meine Formulierung zu hart. Ich hätte auch sagen können: Leider ist der Compiler nicht so schlau ein gleichförmiges mehrdimensionales dynamisches Array anders zu behandeln als ein ungleichförmiges mehrdimensionales dynamisches Array. Ohne dies jemals zu prüfen, ging ich bisher davon aus, dass die Sequenz
Code:
etwas anderes wäre als
a: array of array of Integer;
Code:
Ich habe jetzt gelernt: Sofern die Darstellung des Arrays im Speicher eine Rolle spielt, muss der Programmierer ein gleichförmiges mehrdimensionales dynamisches Array selbst verwalten (wie in #12 gezeigt).
a: array of TIntegerDynArray;
|
AW: Array SCHNELL auf Null setzen
Zitat:
Delphi-Quellcode:
wird also mit einem Aufruf von
arr: array of array of Integer
Delphi-Quellcode:
ebenso mit Nullen initialisiert wie ein eindimensionales.
SetLength(arr, 10, 20)
|
AW: Array SCHNELL auf Null setzen
Hallo,
also ich verlasse mich nicht auf automatisches Setzen des Compilers. Da wir Datenbankprogramme entwickeln, spielt der Overhead des Initialisierens hier überhaupt keine Rolle. Heiko |
AW: Array SCHNELL auf Null setzen
Zitat:
|
AW: Array SCHNELL auf Null setzen
Zitat:
Gruß K-H |
AW: Array SCHNELL auf Null setzen
Zitat:
![]() Das sind so dermaßen grundlegende Dinge in der RTL, die nicht einfach in irgendeiner Version verändert werden. |
AW: Array SCHNELL auf Null setzen
Zitat:
|
AW: Array SCHNELL auf Null setzen
Zitat:
Gruß K-H |
AW: Array SCHNELL auf Null setzen
Zitat:
Wenn du mir die eine andere Pascal Implementierung zeigst, die generics, closures und enhanced rtti kann, dann können wir nochmal über meinen derzeit nur Embarcadero kompatiblen Code sprechen :) |
AW: Array SCHNELL auf Null setzen
Also 'cargo cult programming' ist das ja nun nicht, wenn ich eine Variable explizit initialisiere, d.h. auf 0 setze. Denn manchmal meckert der Compiler und manchmal nicht, manchmal muss man initialisieren, manchmal nicht. Das ist doch inkontinent inkonsistent.
Wenn ich ein Array auf '1' initialisiere, muss ich Initialisierungscode schreiben, bei Initialisierung auf '0' nicht? Was soll das? Man *kann* auf das Nullen verzichten, denn die RTL oder auch Windows macht das schon für einen, aber aus Dokumentationsgründen sollte man (finde ich) Werte explizit initialisieren. Dann fällt man auch nicht in den Matsch, wie Du in ![]() Ich persönlich neige dazu, die Initialisierung grundsätzlich vorzunehmen. Ausgenommen, ich benötige jede Nanosekunde an Performance. (*) Ein *SEHR* empfehlenswerter Blog, liebe Mitleser! |
AW: Array SCHNELL auf Null setzen
Wenn man schon bei so rudimentären Dingen der RTL nicht vertraut, sollte man besser alles selber schreiben[Zynikmodus] auch den Compiler und das Betriebssystem, denn man weiss ja nicht, welchen Mist die verantwortlichen Entwickler verzapft haben[/Zynikmodus]
|
AW: Array SCHNELL auf Null setzen
Zitat:
Zitat:
![]() |
AW: Array SCHNELL auf Null setzen
Zitat:
Es ist einfach nicht möglich alle SubArrays in eine Reihe zu legen (OK, möglich teilweise schon, aber sinnlos), um dann alles mit einem FillChar füllen zu können. Das fällt sofort auf, wenn man weiß wie so ein dynamisches Array aufgebaut ist und daß die Verwaltungsdaten (Länge und Referenzzählung) auch noch vor dem Ersten (Nullten) Feld liegen. |
AW: Array SCHNELL auf Null setzen
Zitat:
Im Ernst. Immer Initialisieren hilft. und PAttern wie:
Delphi-Quellcode:
Sind einfacher und sicherer, wenn sie so stringent durchgezogen werden, das selbst die Reihenfolge der Finalisierungen umgekehrt zu den Initialisierungen ist (sofern sinnvoll). Einfach oberspießige Ordnung. Normalerweise nicht mein Ding, aber hier schon.
initialization
InitializeGlobalStuff(); finalization FinalizeGlobalStuff(); und Constructor Create(); begin InitializeFields(); End; Destructor Destroy(); begin FinalizeFields(); End; Und meine Initialisierungen IMMER explizit (dafür vielleicht redundant). WTF. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:45 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 by Thomas Breitkreuz