Effizienter byte-Zugriff auf ein long[]-Array

LucasGlockner

Mitglied
Hallo,

kann man in Java irgendwie auf ein long[]-Array als byte[] zugreifen, ohne die Daten hin und her kopieren zu müssen?

Hintergrund: Ich habe ein Algorithmus der als Zustand ein long[]-Array benutzt. Die meisten Berechnungsschritte arbeiten dabei direkt auf den long-Werten, also auf ℤ/n mit n = 2^64. Es gibt aber einen Schritt, wo direkt die einzelnen Bytes modifiziert werden müssen!

Anders ausgedrückt, was ist das Java-Äquivalent zu folgendem C#- bzw. JavaScript- bzw. Python-Code?
C#:
long[] array = new long[] { /* ... */ };
fixed (ulong* buffer = array)
{
    byte* bytes = (byte*)buffer;
    for (int pos = 0; pos < NUHASH_BYTES; ++pos)
    {
        bytes[pos] = SBOX[bytes[pos]];
    }
}
Javascript:
let array = new BigUint64Array ([ /* ... */ ]);
const view = new DataView(array.buffer);
const begin = view.byteOffset, end = begin + view.byteLength;
for (let offset = begin; offset < end; ++offset) {
    view.setUint8(offset, SBOX[view.getUint8(offset)]);
}
Python:
array = arr.array('Q', [ ... ])
mem_view = memoryview(array).cast('B')
for i in range(len(view)):
    mem_view[i] = SBOX[mem_view[i]]


Danke!
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Bytebuffer könnte eine Variante sein, ansonsten selber rechnen und mit Bitmasken arbeiten.

Die C-Variante ist so zumindest nicht möglich, in Java sind byte[] und long[] einfach unterschiedliche Typen.
 

LucasGlockner

Mitglied
Bytebuffer könnte eine Variante sein, ansonsten selber rechnen und mit Bitmasken arbeiten.
Kannst Du das genauer ausführen?

Soweit ich sehe, klappt das auch mit ByteBuffer nur indem man die Daten hin und her kopiert, was natürlich ziemlich ineffizient wäre:
Java:
final long[] array = new long[] { /* ... */ };
final ByteBuffer buffer = ByteBuffer.allocate(array.length * Long.BYTES);

for (final long value : array) {
    buffer.putLong(value);
}

for (int i = 0; i < buffer.capacity(); ++i) {
    buffer.put(i, SBOX[buffer.get(i)]);
}

for (int i = 0, j = 0; i < array.length; ++i, j += Long.BYTES) {
    array[i] = buffer.getLong(j);
}

Es gibt zwar ByteBuffer.wrap(), was aber leider nur mit einem byte[]-Array, nicht aber mit einem long[] funktioniert 😟

LongBuffer.wrap() funktioniert, aber aus unverständlichen Gründen fehlt LongBuffer.asByteBuffer().

ByteBuffer.asLongBuffer() hingegen existiert. Aber das ist genau die umgekehrte Richtung, die hier benötigt wird... 🙄

Die C-Variante ist so zumindest nicht möglich, in Java sind byte[] und long[] einfach unterschiedliche Typen.

Schon klar, dass es unterschiedliche Typen sind.

Aber in so ziemlich jeder anderen Sprache (C#, JavaScript, Python, etc.) kann man sich ein byte-"View" für das long (uint64) Array holen und darüber die Daten auf der byte-Ebene zugreifen/manipulieren. Gibt es tatsächlich in Java nichts entsprechendes ???
 

httpdigest

Top Contributor
Aber in so ziemlich jeder anderen Sprache (..., JavaScript, ...) kann man sich byte-"View" für das Array holen und dann die Daten auf der byte zugreifen/manipulieren.
Also zumindest in JavaScript kannst du keine byte-orientierte View auf ein multi-byte-Wert Typed Array haben. Ausgangspunkt einer View ist immer zuerst ein byte-basierter ArrayBuffer, aus dem du dann multi-byte-basierte Typed Arrays (wie etwa ein Int32Array) als Views erzeugen kannst. Aber ja nicht umgekehrt (was du machen möchtest).
Und außerhalb der Typed Arrays gibt es sowieso nur number[] (als double), wo du auch nicht byte-basiert drauf zugreifen kannst.

EDIT: Und tatsächlich ist es in C Undefined Behaviour (also explizit nicht in dem Standard spezifiziert - und jeder Compiler kann hier machen, was er will), wenn du einen Pointer vom Typ T* in einen anderen Pointer U* konvertierst, und dann U* dereferenzierst. Auf den meisten Plattformen funktioniert das aber, weil sie Speicher als kontinuierliche Anreihung individuell adressierbaren Bytes ansehen und es auf Plattformebene im Speicher kein Unterschied zwischen byte und int, long, etc. gibt (außer natürlich alignment-Voraussetzungen beim Zugriff).
Streng genommen ist also das von dir gezeigte C-Programm undefined behaviour (aber welches C-Programm ist schon nicht UB was den C-Standard angeht).
 
Zuletzt bearbeitet:

LucasGlockner

Mitglied
Also zumindest in JavaScript kannst du keine byte-orientierte View auf ein multi-byte-Wert Typed Array haben. Ausgangspunkt einer View ist immer zuerst ein byte-basierter ArrayBuffer, aus dem du dann multi-byte-basierte Typed Arrays (wie etwa ein Int32Array) als Views erzeugen kannst. Aber ja nicht umgekehrt (was du machen möchtest).
Und außerhalb der Typed Arrays gibt es sowieso nur number[] (als double), wo du auch nicht byte-basiert drauf zugreifen kannst.
Doch das geht, wenn man, wie heutzutage empfohlen, ein Uint32Array oder Uint64Array benutzt. Beispiel-Code siehe oben.

EDIT: Und tatsächlich ist es in C Undefined Behaviour (also explizit nicht in dem Standard spezifiziert - und jeder Compiler kann hier machen, was er will), wenn du einen Pointer vom Typ T* in einen anderen Pointer U* konvertierst, und dann U* dereferenzierst. Auf den meisten Plattformen funktioniert das aber, weil sie Speicher als kontinuierliche Anreihung individuell adressierbaren Bytes ansehen und es auf Plattformebene im Speicher kein Unterschied zwischen byte und int, long, etc. gibt (außer natürlich alignment-Voraussetzungen beim Zugriff).
Streng genommen ist also das von dir gezeigte C-Programm undefined behaviour (aber welches C-Programm ist schon nicht UB was den C-Standard angeht).
Ich sprach allerdings auch von C# (das Java-Äquivalent auf der .NET Plattform), nicht C. Beispiel-Code siehe oben.
 
Zuletzt bearbeitet:

LucasGlockner

Mitglied
Anscheinend kann man Byte-Zugriff mittels "theUnsafe" erhalten:

Java:
private static final Unsafe UNSAFE;
private static final int LONG_ARRAY_OFFSET;
static {
    try {
        final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        UNSAFE = (Unsafe) theUnsafe.get(null);
        LONG_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(long[].class);
    } catch (Exception e) {
        throw new ExceptionInInitializerError("Cannot access Unsafe!");
    }
}
Java:
private static void substitute(final long[] buffer) {
    final int limit = LONG_ARRAY_OFFSET + buffer.length * Long.BYTES;
    for (int pos = LONG_ARRAY_OFFSET; pos < limit; ++pos) {
        UNSAFE.putByte(buffer, pos, SBOX[UNSAFE.getByte(buffer, pos) & 0xFF]);
    }
}


Interessanterweise ist diese Lösung bei meinem Test sogar minimal langsamer als:

Java:
private static void substitute(final long[] buffer) {
    for (int pos = 0; pos < buffer.length; ++pos) {
        final long value = buffer[pos];
        buffer[pos] =
            ((SBOX[(int)(value >>> 0x00) & 0xFF] & 0xFFL) << 0x00) |
            ((SBOX[(int)(value >>> 0x08) & 0xFF] & 0xFFL) << 0x08) |
            ((SBOX[(int)(value >>> 0x10) & 0xFF] & 0xFFL) << 0x10) |
            ((SBOX[(int)(value >>> 0x18) & 0xFF] & 0xFFL) << 0x18) |
            ((SBOX[(int)(value >>> 0x20) & 0xFF] & 0xFFL) << 0x20) |
            ((SBOX[(int)(value >>> 0x28) & 0xFF] & 0xFFL) << 0x28) |
            ((SBOX[(int)(value >>> 0x30) & 0xFF] & 0xFFL) << 0x30) |
            ((SBOX[(int)(value >>> 0x38) & 0xFF] & 0xFFL) << 0x38);
    }
}

🤔
 
Zuletzt bearbeitet:

Robert Zenz

Top Contributor
Ist das ein Java 9+ Grund wieso die da Reflektion machen anstelle von Unsafe.getUnsafe()?

Interessanterweise ist diese Lösung bei meinem Test sogar minimal langsamer als:
Ohne es jetzt probiert zu haben, koennte einige Gruende haben. Zwei die mir einfallen sind die "kuerzere" Schleife beim long Array und moeglicherweise CPU Caches die man bei der Unsafe Methode eher verfehlen wird. Letzteres ist aber geraten und wahrscheinlich falsch. Eventuell hat der Unsafe Zugriff auf den Speicher aber noch andere Auswirkungen, ich weisz dass die JVM Werte durchaus cachen kann je nach Thread, eventuell zerlegt der Unsafe Zugriff dort irgendwas und dann muessen Zustaende invalidiert werden.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
F Lesen effizienter als schreiben? Allgemeine Java-Themen 4
N Erste Schritte [HILFE] effizienter,leistungsfähigermbackground Pixelbot Allgemeine Java-Themen 5
U Variablen Stringarrays mit wenig verschiedenen Zeichen effizienter speichern Allgemeine Java-Themen 10
Fu3L Input/Output Brauche Rat bei effizienter Speicherung großer Datenmengen Allgemeine Java-Themen 21
Iron Monkey Object in Datei effizienter lesen / schreiben Allgemeine Java-Themen 13
L verkettete Listen oder Arrays + Indexlisten effizienter? Allgemeine Java-Themen 3
B Effizienter Suchalgorithmus gesucht Allgemeine Java-Themen 10
M Was ist schneller und effizienter GZIP(java) oder 7zip ? Allgemeine Java-Themen 5
Encera Größe eines Objektes in Byte berechnen Allgemeine Java-Themen 2
M Optimierung einer Methode (byte-Geraffel) Allgemeine Java-Themen 2
Noahscript Aus einem byte Array Steuerungszeichen und Code bekommen und ersetzen Allgemeine Java-Themen 3
Thallius unsigned byte Allgemeine Java-Themen 18
N Byte Array in Java "dekomprimieren" Allgemeine Java-Themen 3
kodela Datentypen byte als unsigned interpretieren Allgemeine Java-Themen 23
W String -> byte[] -> String - Sieht jemand was ich nicht sehe? Allgemeine Java-Themen 10
TheWhiteShadow 2D-Grafik GIF Library mit byte output Allgemeine Java-Themen 10
K Data Konverter - Probleme mit Byte[] Kodierung Allgemeine Java-Themen 3
kodela Byte Order Mark (BOM) bei readLine() ignorieren Allgemeine Java-Themen 5
A Byte zu String Allgemeine Java-Themen 4
RalleYTN Datentypen Unsignierter Byte zum signierten Byte Allgemeine Java-Themen 2
X Datentypen Byte geht nicht höher als 126 auch nicht mit casten? Allgemeine Java-Themen 22
R Byte Array Zeichensuche Allgemeine Java-Themen 6
M Null byte in verschiedenen charsets Allgemeine Java-Themen 2
S Byte Array welches in Laufzeit aufgelöst wird // Objekt Array Allgemeine Java-Themen 3
O Byte-Array zu String Allgemeine Java-Themen 7
D Decodierung von Mp3-byte[] Allgemeine Java-Themen 4
A ByteBuffer.get(byte[] dst,int offset,int length) Allgemeine Java-Themen 2
A RandomAccessFile.read(byte[] b) Allgemeine Java-Themen 9
P Datentypen Warum überhaupt Byte ? Allgemeine Java-Themen 12
P Datentypen String-Daten zu Byte-Zahlen konvertieren - Komme nicht weiter nach vielem versuchen :-/ Allgemeine Java-Themen 7
E Byte zu String & umgekehrt Allgemeine Java-Themen 3
B BufferedWriter in InputStream oder Zeichen-Stream in Byte-Stream Allgemeine Java-Themen 5
M Chart per byte[] in JSP anzeigen Allgemeine Java-Themen 4
E int in byte Allgemeine Java-Themen 6
R ArrayList byte[] abspeichern Allgemeine Java-Themen 4
S byte [] in string und zurück konvertieren Allgemeine Java-Themen 2
G byte ? : Allgemeine Java-Themen 7
E Byte-Array to String: Zeichenkaputt Allgemeine Java-Themen 11
R In einem Byte-Array nach einer gewissen Zahlenfolge suchen Allgemeine Java-Themen 7
hdi Speicherbelegung byte, short, int Allgemeine Java-Themen 8
J byte - hex - byte.. casten Allgemeine Java-Themen 8
R byte[] to String Konvertieren Allgemeine Java-Themen 14
A Input/Output Buffered Image zu Byte Array und zurück konvertieren Allgemeine Java-Themen 4
M byte array splitten Allgemeine Java-Themen 3
J Hex-String zu byte transformieren Allgemeine Java-Themen 7
T Zu doof für byte-Umrechnung ... Allgemeine Java-Themen 3
W CRC32 aus byte array Allgemeine Java-Themen 5
F byte[] aus einem BufferedImage Allgemeine Java-Themen 3
L byte -> byte[1] -> byte Allgemeine Java-Themen 2
P Einzelne Bits in einem Byte-Array setzen Allgemeine Java-Themen 2
Kr0e Synchronisieren: boolean,byte,char ? Allgemeine Java-Themen 2
S Überprüfung/Parsen eines Byte-Arrays Allgemeine Java-Themen 9
Semox Byte-Manipulation eines Bildes Allgemeine Java-Themen 7
Meldanor For-Schleifen - byte statt int? Allgemeine Java-Themen 11
C int zu byte cast - verständnis Allgemeine Java-Themen 3
R int to byte[] Array Allgemeine Java-Themen 4
MQue byte[] Array to Integer Allgemeine Java-Themen 4
MQue Byte to Int convertieren Allgemeine Java-Themen 2
R Double Werte aus byte[] auslesen Allgemeine Java-Themen 5
W Verwendung von byte Allgemeine Java-Themen 9
G zu lange Byte code dateien Allgemeine Java-Themen 6
G String in byte- Array Allgemeine Java-Themen 3
E Byte [] nach hex, dann nach dec Allgemeine Java-Themen 2
A Performance: byte[] in byte[][][] konvertieren Allgemeine Java-Themen 2
G 2 x byte zusammenkopieren Allgemeine Java-Themen 7
G byte nach int Allgemeine Java-Themen 3
foobar Object to byte[] ohne Serializable Allgemeine Java-Themen 6
data89 Die Größe eines Strings in Byte berechnen? Allgemeine Java-Themen 12
G Byte- List mit einem Iterator durchlaufen Allgemeine Java-Themen 5
W Konflikt byte->int, in.read->arraycopy Allgemeine Java-Themen 7
T "unsigned" byte[] -> BigInteger Allgemeine Java-Themen 2
F byte in hex-String oder: Wer hat in Mathe aufgepasst Allgemeine Java-Themen 3
T Socket Server Anwendung - Empfang eines Byte-Arrays Allgemeine Java-Themen 7
J NumberFormatException bei String->byte[] Allgemeine Java-Themen 12
ARadauer Blob aus byte Array erstellen? Allgemeine Java-Themen 3
T Object -> byte[] Allgemeine Java-Themen 5
G Byte[] zeichenweise lesen Allgemeine Java-Themen 4
G byte[] mit Strings füllen Allgemeine Java-Themen 2
B int -> byte Allgemeine Java-Themen 2
G file --> byte[] Allgemeine Java-Themen 7
E Problem beim Dateien kodieren ("Byte = Byte +1") Allgemeine Java-Themen 3
I String -> byte[] -> String Allgemeine Java-Themen 2
D byte nach integer? Allgemeine Java-Themen 4
MQue int in byte Allgemeine Java-Themen 18
G Maximalgröße von byte[] buffer Allgemeine Java-Themen 7
E String -> byte[] Allgemeine Java-Themen 6
C Byte[] to String Allgemeine Java-Themen 7
D datei in byte[]-array schreiben Allgemeine Java-Themen 6
D byte[] problem Allgemeine Java-Themen 3
MQue ArrayList in ein byte- Array Allgemeine Java-Themen 7
B ein spezielles Byte-Array sortieren Allgemeine Java-Themen 11
T OutputStream - Event bei Byte-Fluss Allgemeine Java-Themen 5
J byte-Array in Hashmap speichern? Allgemeine Java-Themen 3
S Problem beim Einlesen von byte-werten aus datei Allgemeine Java-Themen 2
J byte-Array als String übers http schicken Allgemeine Java-Themen 8
F List<String> zu byte[] Allgemeine Java-Themen 7
L byte vs. int Allgemeine Java-Themen 6
G Umwandlung Byte in Integer Allgemeine Java-Themen 12
N Byte-Code entschlüsseln (Bitmasks?) Allgemeine Java-Themen 3
R byte - string? Allgemeine Java-Themen 10

Ähnliche Java Themen

Neue Themen


Oben