4 Bytes in Heap zu int

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
udok
Beiträge: 40
Registriert: 01.02.2022, 17:34

Re: 4 Bytes in Heap zu int

Beitrag von udok »

Schön, das sich da was tut.
Aber wenn man den Byteswap anders formuliert, geht es wieder nicht...

Code: Alles auswählen

// vs2022 Ok, clang-cl Ok
int byteSwap1(int n)
{
    return  ((n & 0xff) << 24u) |
            ((n & 0xff00) << 8u) |
            ((n & 0xff0000) >> 8u) |
            ((n & 0xff000000) >> 24u);
}

__forceinline unsigned short xbyteSwap16(unsigned short n)
{
    n = (BYTE)(n >> 8) | ((unsigned char)n << 8);
    return n;
}

// vs2022 Fail, clang-cl Ok
unsigned byteSwap2(unsigned n)
{
    unsigned short nl, nh;

    nl = xbyteSwap16((unsigned short)n);
    nh = xbyteSwap16((unsigned short)(n >> 16));

    return ((unsigned short)nl << 16) | (unsigned short)nh;
}

// VS2008 OK, vs2022 Ok, clang-cl Ok
unsigned byteSwap3(unsigned n)
{
    return _byteswap_ulong(n);
}
Benutzeravatar
starcow
Establishment
Beiträge: 522
Registriert: 23.04.2003, 17:42
Echter Name: Mischa Schaub
Kontaktdaten:

Re: 4 Bytes in Heap zu int

Beitrag von starcow »

Jonathan hat geschrieben: 20.11.2022, 07:56 Soweit ich weiß, hast du beim Öffnen im Textmodus zusätzliche automatische Konvertierung von Dingen wie New-Line Characters, während dir der Binärmodus die Datei so liefert, wie sie ist.
Mir scheint der Text-Modus ein wenig ein Relikt der Vergangenheit zu sein. Wenn du z.B. eine Datei im Textmodus einliest und direkt danach wieder schreibst, kann der Inhalt danach anders sein, weil Zeichen automatisch konvertiert wurden. "Relikt der Vergangenheit" deshalb, weil, soweit ich weiß, zwar Dinge wie Newlines berücksichtigt werden, aber sowas wie Unicode wiederum nicht. Du musst also ggf. nach dem Lesen trotzdem noch von Hand Anpassungen vornehmen, in Fällen wo das wichtig ist würde ich also direkt alles binär Öffnen und dann gleich alles von Hand machen.
dot hat geschrieben: 20.11.2022, 23:46 .bmp Files sind keine Textdateien, du kannst die im Textmodus gar nicht korrekt lesen weil Textmodus macht Dinge wie \r\n in \n übersetzen, filtert also potentiell Bytes aus dem Stream raus.

Fun fact: Das war der Grund für den Bug, der immer noch der Bug ist, der mich mit großem Abstand am meisten Zeit gekostet hat. Hab damals das ganze Programm vermutlich dreimal from Scratch neu geschrieben, weil ich mir einfach nicht erklären konnte wieso beim Lesen des 3d Models erst alles richtig läuft aber dann ab einem zufälligen Punkt auf einmal plötzlich nur Müll daherkommt… bis ich eines Tages durch Zufall auf einer MSDN Seite gelandet bin, wo im Text indirekt etwas erwähnt wurde, dass bedeutet hätte, dass Textmodus der Default sein könnte. Die Idee dass sowas wie Textmodus der Default wäre, war für mein naives Selbst einfach dermaßen unvorstellbar… tbf, ich finde es immer noch einfach nur falsch…
Ok, danke, alles klar! Dann werde ich künftig darauf achten, alles im binary Modus einzulesen. :-)
udok hat geschrieben: 28.11.2022, 22:02
Schön, das sich da was tut.
Aber wenn man den Byteswap anders formuliert, geht es wieder nicht...

Code: Alles auswählen

// vs2022 Ok, clang-cl Ok
int byteSwap1(int n)
{
    return  ((n & 0xff) << 24u) |
            ((n & 0xff00) << 8u) |
            ((n & 0xff0000) >> 8u) |
            ((n & 0xff000000) >> 24u);
}

__forceinline unsigned short xbyteSwap16(unsigned short n)
{
    n = (BYTE)(n >> 8) | ((unsigned char)n << 8);
    return n;
}

// vs2022 Fail, clang-cl Ok
unsigned byteSwap2(unsigned n)
{
    unsigned short nl, nh;

    nl = xbyteSwap16((unsigned short)n);
    nh = xbyteSwap16((unsigned short)(n >> 16));

    return ((unsigned short)nl << 16) | (unsigned short)nh;
}

// VS2008 OK, vs2022 Ok, clang-cl Ok
unsigned byteSwap3(unsigned n)
{
    return _byteswap_ulong(n);
}
Spannend! Auch wenn mir scheint, etwas über meinem Level. Hier gehts aber ausschliesslich darum, wie optimal der Maschinencode ist, den die verschiedenen Compiler erzeugen? Nicht, das die Methode mittels Bitshifting grunsätzlich problematisch wäre?

LG, starcow
Freelancer 3D- und 2D-Grafik
mischaschaub.com
udok
Beiträge: 40
Registriert: 01.02.2022, 17:34

Re: 4 Bytes in Heap zu int

Beitrag von udok »

Da geht es nur um Mikrooptimierungen, die in 99% der Fälle gerade mal ein paar Mikro Joule einsparen.

Ich verwende seit Urzeiten den folgenden Header unter Windows:

Code: Alles auswählen

#if _MSC_VER >= 1400 && !__clang__
/* declaration of the intrinsic byteswap functions is in <stdlib.h> */
# pragma intrinsic(_byteswap_ushort, _byteswap_ulong, _byteswap_uint64)
#endif

#ifndef FORCEINLINE
  #ifdef _MSC_VER
    #define FORCEINLINE __forceinline
  #else /* _MSC_VER */
    #ifdef __GNUC__
      #define FORCEINLINE __attribute__((always_inline))
    #else /* __GNUC__ */
      #pragma message("WARNING: Unsupported Compiler - FORCEINLINE is INLINE")
      #define FORCEINLINE INLINE
    #endif /* __GNUC__ */
  #endif /* _MSC_VER */
#endif /* FORCEINLINE */

#ifdef __cplusplus
extern "C" {
#endif

FORCEINLINE UINT16 ByteSwap16(UINT16 n)
{
#if _MSC_VER >= 1400 && !__clang__
    n = _byteswap_ushort(n);
#elif __GNUC__ > 4 || __clang__
    n = __builtin_bswap16(n);
#else
    n = (BYTE)(n >> 8) | ((BYTE)n << 8);
#endif
    return n;
}

FORCEINLINE UINT32 ByteSwap32(UINT32 n)
{
#if _MSC_VER >= 1400 && !__clang__
    n = _byteswap_ulong(n);
#elif __GNUC__ > 4 || __clang__
    n = __builtin_bswap32(n);
#else
    UINT16 nl, nh;
    nl = ByteSwap16((UINT16)n);
    nh = ByteSwap16((UINT16)(n >> 16));
    n = ((UINT16)nl << 16) | (UINT16)nh;
#endif
    return n;
}

FORCEINLINE UINT64 ByteSwap64(UINT64 n)
{
#if _MSC_VER >= 1400 && !__clang__
    n = _byteswap_uint64(n);
#elif __GNUC__ > 4 || __clang__
    n = __builtin_bswap64(n);
#else
    UINT32 nl, nh;
    nl = ByteSwap32((UINT32)n);
    nh = ByteSwap32((UINT32)(n >> 32));
    n = ((UINT64)nl << 32) | (UINT64)nh;
#endif
    return n;
}

#ifdef __cplusplus
}
#endif

Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: 4 Bytes in Heap zu int

Beitrag von dot »

Krishty hat geschrieben: 28.11.2022, 21:36
dot hat geschrieben: 15.11.2022, 12:18Sicher dass das mit MSVC war und nicht, e.g., clang? Ich versuche seit Jahren, MSVC dazu zu bewegen, einigermaßen effizienten Code für portable Serialization/Deserialization zu generieren; bisher ohne Erfolg…
Lustig: Heute veröffentlicht das Team einen Artikel, dass sie diese Optimierung vor Kurzem in Visual Studio 2022 implementiert haben.
leider (noch) nicht ganz: https://developercommunity.visualstudio ... n/10260231
Benutzeravatar
Krishty
Establishment
Beiträge: 8227
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: 4 Bytes in Heap zu int

Beitrag von Krishty »

*seufz* Vielleicht, wenn sie GPTChat gekauft haben …

Hab’s direkt man upvoted.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 358
Registriert: 03.10.2003, 12:47

Re: 4 Bytes in Heap zu int

Beitrag von NytroX »

*seufz* Vielleicht, wenn sie GPTChat gekauft haben …
Haben sie ja quasi: https://www.cnbc.com/2023/01/23/microso ... penai.html
smurfer
Establishment
Beiträge: 195
Registriert: 25.02.2002, 14:55

Re: 4 Bytes in Heap zu int

Beitrag von smurfer »

Noch eine Randnotiz zum Anfang des Threads: Ich denke auch, dass BMP eine gute Übung ist, wenn man etwas im Low-Level-Bereich lernen möchte. Als ich vor etwa einem Monat durch die "Werbung" von xq mit Zig begonnen habe, war ich auch auf der Suche nach solchen einfachen Beispielprojekten, um verschiedene grundlegende Aspekte der Sprache vertiefen, wie hier die die Speicherauslegung. Direkt mit jpeg zu starten würde zu Beginn weniger die Sprache als vielmehr das Verfahren vertiefen.
Antworten