Hallo,
Welche Umgebung? Hast Du Visual Studio98 mit
Visual C++ 6?
Ja. Aber mit C++ kann ich nicht umgehen.
Damit ist alles genannte sehr einfach zumachen.
In VB6 kann ich mit …
CopyMemory Lib „kernel32“ Alias „RtlMoveMemory“ (pDst As Any,
pSrc As Any, ByVal ByteLen As Long)
… einige Bytes (Anzahl steht in Bytelen) verschieben. Um
aber den Inhalt von zwei Bereichen auszutauschen muss ich das
drei mal aufrufen und dann ist ein ‚Ringtausch‘ mit VB
schneller. Ein ‚SWAP‘ gibt es nicht, b.z.w. ich konnte keine
entsprechende DLL finden.
Ich verstehe das Problem nicht ganz. *Welchen*
Speicherbereich?
In VB6 erfahre ich mit StrPtr() den Pointer eines Strings, mit VarPtr() den Pointer einer Variablen und mit Array(Index) wird der Pointer auf ein Feld in einem Array übergeben. Wenn ich dann Integer Variablen bearbeiten möchte, gebe ich zwei Byte an und kann die Inhalte mit CopyMemory bearbeiten.
Bei zwei Byte bringt das kaum Vorteil, wenn ich aber ein ByteArray damit bearbeite und einige bis einige Tausend Bytes verschiebe, ist der Geschwindigkeitsgewinn gegenüber einer Zählschleife mit VB enorm.
Einen, den Du Dir selber geholt hast? Das wäre, gerade in
C/C++, trivial. Im Prinzip würde man so vorgehen:
- immer „maschinenwortweise“ tauschen (schnell),
OK, auch wenn Wortweise schnell ist, wäre das ein Gewinn, ich kann mich ja daran anpassen.
- aufpassen, wenn Byte-Länge nicht durch Wortgröße (4)
teilbar,
- aufpassen, dass Startadresse des Tauschens durch 4 teilbar
Klar. Ich werde das gleich mal prüfen, aber ich nehme an, daß VB die Pointer von Long-Variablen auf entsprechende Adressen setzt.
eventuell muss man die ersten und letzten Bytes gesondert
behandeln. Bei sehr grossen Speicherbereichen lohnt sich
das aber extrem ,wenn die Maschinenwortzugriffe DWORD-aligned
sind.
Ich nehme an, daß mir VB ‚passende‘ Pointer setzen wird, wenn ich die Arrays oder variablen als Long deklariere.
Beispiel: (WIN32):
...
char spa[] = { 'h','a','l','l','o',' ','o','b','e','n','\0'};
char spb[] = { 'u','n','t','e','n',' ','a','u','c','h','\0'};
int Bytelen = sizeof(spa);
unsigned long \*psrc = (unsigned long \*)spa;
unsigned long \*pdst = (unsigned long \*)spb;
unsigned long MWordLen = (Bytelen+3) / 4; /\* Achtung wenn:
Bytelen % 4 != 0
/\* fast swap loop, je 32bit (Maschinenwort) pro Schritt \*/
for( ; MWordLen--; ++pdst,++psrc) \*pdst ^= \*psrc ^= \*pdst ^=
\*psrc;
...
hmmm, das bespreche ich mal mit meinem Sohn, der kann das eventuell lesen.
Aber das hängt natürlich davon ab, was Du tun
willst. Bei
wenigen 10 KB kann man auch einfach byteweise tauschen.
Inzwischen geht es mir nicht mehr um eine konkrete Anwendung, auch wenn der Gedanke dadurch entstanden ist, daß ich einem Freund eine Prozedur beschleunigen möchte. Ich erzähle erst mal, was der treibt … Lotto.
Ein Byte-Array (1 to 49) wird mit 1 - 49 gefüllt.
Dann wird ein Zufallswert ermittelt und das ermittelte Byte mit dem letzten Byte getauscht.
MerkVariable = Array(Index)
Array(Index) = Array(49)
Array(49) = MerkVariable
Genau diese Stelle möchte ich beschleunigen.
Wenn das per DLL geht, wäre es aber angenehm, wenn man damit auch gleich noch andere Fälle erschlagen könnte.
VB-Beispiel: Das …
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias \_
"RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Command1\_Click()
Dim i As Integer 'Index für Zählschleifen
Dim P1 As Integer 'Position1
Dim P2 As Integer 'Position2
Dim l As Integer 'Länge, Anzahl zu verschiebender Bytes
Dim AM() As Byte 'Array zum zwischenspeichern
Dim Arr(100) As Byte 'Das Array zum Arbeiten
'erst mal das Array füllen, nur Beispiel
For i = 0 To 100
Arr(i) = i
Next
l = 7 'nur Beispiel, 7 Bytes verschieben
P1 = 32 'Positionen, auch nur Beispiel
P2 = 74
ReDim AM(l) 'Das Array zum zwischenspeichern auf \_
die richtige größe bringen
CopyMemory AM(0), Arr(P1), l
CopyMemory Arr(P1), Arr(P2), l
CopyMemory Arr(P2), AM(0), l
End Sub
… müsste man mit der richtigen Dll doch so lösen können: …
Option Explicit
Private Declare Sub SwapMemory Lib "?????" \_
(pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Command1\_Click()
Dim i As Integer 'Index für Zählschleifen
Dim l As Integer 'Länge, Anzahl zu verschiebender Bytes
Dim Arr(100) As Byte 'Das Array zum Arbeiten
'erst mal das Array füllen, nur Beispiel
For i = 0 To 100
Arr(i) = i
Next
l = 7 'nur Beispiel, 7 Bytes verschieben
P1 = 32 'Positionen, auch nur Beispiel
P2 = 74
SwapMemory Arr(P1), Arr(P2), l 'gibt's scheinbar (noch) nicht.
End Sub
… was deutlich schneller wäre.
Nur kann ich das nicht selbst und mein Sohn auch (noch) nicht.
Gruß, Rainer