Wie kann ich einen beliebig großen Speicherbereich in read/write mappen?



  • Was ist jetzt die Frage? (Was hat Assembler mit Qt zu tun?)

    Was generiert der Compiler denn genau? Vielleicht kann dir hier jemand helfen die C++-Variante zu optimieren.



  • Die C++ Frage ist, wie ich einen Speicherbereich von N Bytes mappen kann, sodass ich diesen sorgenlos nutzen kann.
    Der Assembler Code soll dort dann die Arrays generieren.

    Hier ein Beispiel, was ich an dem vom Compiler generierten Code sehr kontraproduktiv finde:

    unsigned __int64 i = 0;
    00007FF76574229B  mov         qword ptr ,0  
    	unsigned __int64 c = 0x200000000;
    00007FF7657422A3  mov         rax,200000000h  
    00007FF7657422AD  mov         qword ptr [c],rax  
    	while (i < c)
    00007FF7657422B1  mov         rax,qword ptr [c]  
    00007FF7657422B5  cmp         qword ptr [i],rax  
    00007FF7657422B9  jae         main+68h (07FF7657422C8h)  
    	{
    		i++;
    00007FF7657422BB  mov         rax,qword ptr [i]  
    00007FF7657422BF  inc         rax  
    00007FF7657422C2  mov         qword ptr [i],rax  
    	}
    

    In Assembler kann ich alle Variablen in Register packen. Der Zugriff auf Register ist sehr viel schneller:

    .data
    .code
    assembly proc
    
    mov rax, 0
    mov rbx, 0200000000h
    asdf:
    cmp rax, rbx
    inc rax
    jbe asdf
    
    ret
    xor rax, rax
    assembly endp
    
    end
    

    Die Schlife in Assembler kommt in einen Fünftel der Zeit zum Ende.
    Das Nutzen des [i]register* Befehls hat nichts gebracht.
    Um die sehr langen Arrays schnell abarbeiten zu können, möchte ich also die Adresse des Dump-Beginns im Speicher in r8 packen, die Addresse des neu verfügbaren Speichers, den Wert 3, um zu überprüfen, ob es sich um einen Potentiellen Pointer handelt und je nach dem, was sonst noch gebraucht wird. Die einzigsten Speicherzugriffen wären nur noch die, wenn auf dem Dump und in das Array zugegriffen wird.
    Daher fang ich erst gar nicht an diese so häufig repetierenden Schleifen in einer höheren Sprache zu schreiben.

    Es gibt bereits ein paar solcher Programme, die aber entweder in Java oder C# geschrieben wurden. Die Suche nach Pointern, die wieder auf Pointer verweisen dauert einfach zu lange.



  • Wie hast du getestet?
    Mit welchen Compiler und mit welchen Einstellungen?
    Mit aktiven Optimierungen oder ohne?



  • firefly schrieb:

    Wie hast du getestet?

    Da ich noch nicht so ganz herausgefunden habe, wie ich in Qt Assembler direkt compilieren oder eine .o Datei mit einbeziehen kann, habe ich das in Visual Studio getestet.
    Man kann einach Breakpoints setzen und wenn das Programm angehalten wurde mittels Rechtsklick auf die Zeile den Assembler-Code untersuchen.
    Mit der Funktion time() habe ich verglichen wie viel schneller bzw langsamer die Funktionen ausgeführt werden:

    extern "C" __int64 _stdcall assembly(__int64 x);
    
    int main()
    {
    	unsigned int timeStart = time(0);
    	cout << "Performing C++ loop\n";
    	register unsigned __int64 i = 0;
    	register unsigned __int64 c = 0x200000000;
    	while (i < c)
    	{
    		i++;
    	}
    	cout << "C++ loop took " << time(0) - timeStart << " seconds\n\n\n\n";
    
    	timeStart = time(0);
    	cout << "Performing ASM loop\n";
    	assembly();  // dieselbe Schleife, nur in Assembler
    	cout << "Assembly loop took " << time(0) - timeStart << " seconds\n";
    
    	system("pause");
        return 0;
    }
    

    Die C++ Schleife brauchte 19 Sekunden, die Assembler-Schleife nur 4.
    Klar wurde, wenn ich mit einem Array arbeite auch Speicherzugriffe von Nöten sein, aber ich kann den Rest der Variablen (Offset, Adresse des Arrays, Adresse des RAM-Dumps, usw) in den Registern behalten.

    firefly schrieb:

    Mit welchen Compiler und mit welchen Einstellungen?

    Habe lediglich die Einstellung auf x64 geändert.

    firefly schrieb:

    Mit aktiven Optimierungen oder ohne?

    Optimieriung: Maximum Speed (/O2),
    Favor Maximum Speed or Size: Inheriet/vererbt (ich weiß nicht, wie genau die deutsche Übersetzung ist, jedenfalls, wenn es nicht vererbt ist, sagt es, dass die beiden Einstellungen zueinander inkompatibel sind)
    Performance hat sich aber nicht geändert.

    Aber unabhängig davon, ob ich nun Assembler nutze oder nicht, brauche ich den frei verfügbaren Speicherbereich. Deswegen dieser Thread..



  • Das wurde bestimmt nicht mit Optimierungen kompiliert. Ein optimierender Compiler (habs mit GCC getestet) kann die ganze Schleife in den Zeilen 9-12 wegoptimieren (ich nehme an der Microsoft C++ Compiler ist aehnlich gut wie GCC). Auf jeden Fall dauert die Ausfuehrung unter Windows nicht 19 Sekunden (habs getestet). Kann es sein, dass der Debugger den nicht optimieren Assembly Code zeigt?

    In deinem Fall irgendwas mit Assembler optimieren zu wollen ist einfach nur sinnlos (ausser du willst wirkliche Optimierungen vornehmen, wie z.B. Cache Prefechting etc.).

    Google mal nach Memory Mapped Files, das koennte dir helfen. Oder nimm einfach malloc , das ist wohl am einfachsten.

    *Edit
    Auch Visual Studio optimiert die gesamte Schleife weg (habs gerade getestet). Ist ja auch relativ offensichtlich wenn man ein wenig Erfahrung mit Compiler-Optimierungen besitzt.



  • Mit malloc funktionierts. danke



  • KratzKatz schrieb:

    Mit malloc funktionierts. danke

    Schreibst du den Code immer noch in Assembly?



  • nur die eigentliche Suche nach den Pointer



  • Wäre es nicht einfacher die Compiler-Optimierungen zu aktivieren?



  • TyRoXx schrieb:

    Wäre es nicht einfacher die Compiler-Optimierungen zu aktivieren?

    Einfacher ja. Aber ob schneller...
    Die Suche nach "einfachen" Pointer funktioniert bereits und dauert bei einem Dump von 1GB größe nicht mal eine Sekunde. Schneller als bei allen anderen Tools dieser Art, die ich kenne



  • KratzKatz schrieb:

    TyRoXx schrieb:

    Wäre es nicht einfacher die Compiler-Optimierungen zu aktivieren?

    Einfacher ja. Aber ob schneller...
    Die Suche nach "einfachen" Pointer funktioniert bereits und dauert bei einem Dump von 1GB größe nicht mal eine Sekunde. Schneller als bei allen anderen Tools dieser Art, die ich kenne

    Zeig mal deinen Assembly Code.


  • Mod

    KratzKatz schrieb:

    TyRoXx schrieb:

    Wäre es nicht einfacher die Compiler-Optimierungen zu aktivieren?

    Einfacher ja. Aber ob schneller...

    Aber ausprobiert hast du es nicht, oder? Gerade bei solchen Dingen optimieren Compiler eigentlich wesentlich besser als jeder Mensch. Handgeschriebener Assemblycode ist erfahrungsgemäß gut für die Ausnutzung ganz besonderer Prozessorfeatures, aber nicht für 0815-Code.


Anmelden zum Antworten