Ho una matrice di tipi uint in C#, Dopo aver controllato se il programma sta lavorando su una macchina little-endian, voglio convertire i dati in un big-endian genere. Poiché la quantità di dati può diventare molto grande ma è sempre uniforme, stavo pensando di considerare due tipi di uint come un tipo ulong, per una performance migliore e programmarlo in ASM, quindi sto cercando un modo molto veloce (il più veloce possibile) Algoritmo di assembler per convertire little-endian in big-endian.Conversione da little-endian a big-endian in ASM
risposta
Per una grande quantità di dati, l'istruzione bswap
(disponibile in Visual C++ sotto gli intrinseci _byteswap_ushort
, _byteswap_ulong
, and _byteswap_uint64
) è la strada da percorrere. Questo supererà anche l'assemblaggio scritto a mano. Queste non sono disponibili in puro C# senza P/Invoke, in modo da:
- utilizzarla solo se si dispone di un sacco di dati scambio di byte.
- Si dovrebbe seriamente considerare di scrivere l'I/O dell'applicazione di livello più basso nel C++ gestito in modo da poter eseguire lo scambio prima di portare i dati in un array gestito. Dovete già scrivere una libreria C++, quindi non c'è molto da perdere e voi eludete tutti i problemi di prestazioni relativi a P/Invoke per algoritmi a bassa complessità che operano su dataset di grandi dimensioni.
PS: Molte persone non sono consapevoli dell'intreccio di byte swap. La loro performance è sorprendente, doppiamente così per i dati in virgola mobile perché li elabora come interi. Non c'è modo di batterlo senza codificare a mano i carichi del tuo registro per ogni singolo caso di scambio di byte, e se dovessi provare, probabilmente otterrai un maggior successo nell'ottimizzatore di quanto tu non abbia mai capito.
stavo pensando di prendere in considerazione due tipi uint come un tipo ulong
Beh, che sarebbe anche scambiare i due valori uint, che potrebbe non essere desiderabile ...
Si potrebbe prova un codice C# in modalità non sicura, che potrebbe effettivamente funzionare abbastanza bene. Come:
public static unsafe void SwapInts(uint[] data) {
int cnt = data.Length;
fixed (uint* d = data) {
byte* p = (byte*)d;
while (cnt-- > 0) {
byte a = *p;
p++;
byte b = *p;
*p = *(p + 1);
p++;
*p = b;
p++;
*(p - 3) = *p;
*p = a;
p++;
}
}
}
Sul mio computer il throughput è di circa 2 GB al secondo.
Si consiglia di ripensare semplicemente il problema, questo non dovrebbe essere un collo di bottiglia. Prendi l'algoritmo ingenuo (scritto in assembly CLI, solo per divertimento). Assumiamo il numero che vogliamo è in numero locale 0
LDLOC 0
SHL 24
LDLOC 0
LDC.i4 0x0000ff00
SHL 8
OR
LDLOC 0
LDC.i4 0x00ff0000
SHL.UN 8
OR
LDLOC 0
SHL.UN 24
OR
Al massimo che è 13 istruzioni (x86) di assemblaggio per il numero (e molto probabilmente l'interprete sarà ancora più intelligente utilizzando registri intelligenti). E non diventa più ingenuo di così.
Ora, si confronti con i costi di
- ottenere i dati caricati in (tra cui qualunque periferiche si sta lavorando!)
- Maniuplation dei dati (fare confronti, per esempio)
- Emissione del risultato (qualunque esso sia)
Se 13 di istruzioni al numero è un pezzo significativo del tempo di esecuzione, allora si sta facendo un compito MOLTO ad alte prestazioni e dovrebbe avere il tuo input nel formato corretto! Probabilmente non useresti un linguaggio gestito perché vorresti avere un controllo molto maggiore su buffer di dati e quant'altro, e nessun controllo di limiti di array aggiuntivi.
Se tale matrice di dati attraversa una rete, mi aspetto che ci siano costi molto maggiori dalla gestione dei socket che da un semplice capovolgimento dell'ordine dei byte, se si tratta di disco, considerare il pre-flipping prima di eseguire questo programma.
- 1. Conversione da Bash shell a conversione binaria da
- 2. Perdita di precisione da Int a virgola mobile a conversione
- 3. Conversione da & a & in Objective-C
- 4. Conversione da vuoto * a oggetto in C#
- 5. Conversione da binario a char in C
- 6. Conversione da varchar a numerico in Informix
- 7. Conversione da Hex a Binary in bash
- 8. Conversione da JSON a XML in Java
- 9. Conversione da String a DateTime in PowerShell
- 10. conversione da decimale a int in C#
- 11. Conversione da modificabile a int in Android
- 12. Conversione da Unicode a stringa in Java
- 13. Conversione da SVG a PNG in Ruby
- 14. Conversione da DateTime a stringa in Julia
- 15. Conversione da byte a int in java
- 16. Conversione da frame a millisecondi in android
- 17. Conversione da ASCII a TBCD in C
- 18. Conversione da double a float in Java
- 19. conversione da gradle a maven plug-in
- 20. Conversione da cinese a pinyin
- 21. Conversione da C a MIPS
- 22. Conversione da GHC.Int.Int64 a Int
- 23. Conversione da ppm a png
- 24. Conversione da BitArray a Byte
- 25. Conversione da Mercurial a Subversion
- 26. Conversione da HTML a XML
- 27. Conversione da svg a jeff
- 28. Conversione da PDF a UIImage
- 29. Conversione da EPS a Xaml
- 30. conversione da emf a jpg
definire per me "molto grande"? –
almeno 1'000'000 uints (forse un po 'meno ma può diventare più grande) –