A bit of cleanup of BalticHash. Added wip simd version
This commit is contained in:
parent
300fe18b10
commit
febbb95b97
@ -20,6 +20,7 @@ package net.szum123321.textile_backup.core.digest;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This algorithm copies construction of SeaHash (https://ticki.github.io/blog/seahash-explained/) including its IV
|
This algorithm copies construction of SeaHash (https://ticki.github.io/blog/seahash-explained/) including its IV
|
||||||
@ -27,33 +28,30 @@ import java.nio.ByteOrder;
|
|||||||
I don't think it matters that much, honestly. One advantage the xoroshift has is that it should be
|
I don't think it matters that much, honestly. One advantage the xoroshift has is that it should be
|
||||||
easier to implement with AVX. Java should soon ship its vector api by default.
|
easier to implement with AVX. Java should soon ship its vector api by default.
|
||||||
*/
|
*/
|
||||||
public class XorSeaHash implements Hash {
|
public class BalticHash implements Hash {
|
||||||
|
protected final static long[] IV = { 0x16f11fe89b0d677cL, 0xb480a793d8e6c86cL, 0x6fe2e5aaf078ebc9L, 0x14f994a4c5259381L};
|
||||||
|
|
||||||
//SeaHash IV
|
//SeaHash IV
|
||||||
private final long[] state = { 0x16f11fe89b0d677cL, 0xb480a793d8e6c86cL, 0x6fe2e5aaf078ebc9L, 0x14f994a4c5259381L};
|
private final long[] state = Arrays.copyOf(IV, IV.length);
|
||||||
private final int buffer_size = (state.length + 1) * Long.BYTES;
|
protected final int buffer_limit = state.length * Long.BYTES;
|
||||||
private final int buffer_limit = state.length * Long.BYTES;
|
protected final byte[] _byte_buffer = new byte[(state.length + 1) * Long.BYTES];
|
||||||
private final byte[] _byte_buffer = new byte[buffer_size];
|
|
||||||
//Enforce endianness
|
//Enforce endianness
|
||||||
private final ByteBuffer buffer = ByteBuffer.wrap(_byte_buffer).order(ByteOrder.LITTLE_ENDIAN);
|
protected final ByteBuffer buffer = ByteBuffer.wrap(_byte_buffer).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
private long hashed_data_length = 0;
|
protected long hashed_data_length = 0;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(byte b) {
|
public void update(byte b) {
|
||||||
buffer.put(b);
|
buffer.put(b);
|
||||||
hashed_data_length += 1;
|
hashed_data_length += 1;
|
||||||
if (buffer.position() >= buffer_limit) round();
|
if (buffer.position() >= buffer_limit) round();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(long b) {
|
public void update(long b) {
|
||||||
buffer.putLong(b);
|
buffer.putLong(b);
|
||||||
hashed_data_length += Long.BYTES;
|
hashed_data_length += Long.BYTES;
|
||||||
if(buffer.position() >= buffer_limit) round();
|
if(buffer.position() >= buffer_limit) round();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(byte [] data) { update(data, 0, data.length); }
|
|
||||||
|
|
||||||
public void update(byte[] data, int off, int len) {
|
public void update(byte[] data, int off, int len) {
|
||||||
int pos = off;
|
int pos = off;
|
||||||
while(pos < len) {
|
while(pos < len) {
|
||||||
@ -67,9 +65,11 @@ public class XorSeaHash implements Hash {
|
|||||||
hashed_data_length += len;
|
hashed_data_length += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue() {
|
public long getValue() {
|
||||||
if(buffer.position() != 0) round();
|
if(buffer.position() != 0) {
|
||||||
|
while(buffer.position() < buffer_limit) buffer.put((byte)0);
|
||||||
|
round();
|
||||||
|
}
|
||||||
|
|
||||||
long result = state[0];
|
long result = state[0];
|
||||||
result ^= state[1];
|
result ^= state[1];
|
||||||
@ -80,8 +80,7 @@ public class XorSeaHash implements Hash {
|
|||||||
return xorshift64star(result);
|
return xorshift64star(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void round() {
|
protected void round() {
|
||||||
while(buffer.position() < buffer_limit) buffer.put((byte)0);
|
|
||||||
int p = buffer.position();
|
int p = buffer.position();
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
|
|
||||||
@ -91,7 +90,7 @@ public class XorSeaHash implements Hash {
|
|||||||
if(p > buffer_limit) {
|
if(p > buffer_limit) {
|
||||||
System.arraycopy(_byte_buffer, buffer_limit, _byte_buffer, 0, buffer.limit() - p);
|
System.arraycopy(_byte_buffer, buffer_limit, _byte_buffer, 0, buffer.limit() - p);
|
||||||
buffer.position(buffer.limit() - p);
|
buffer.position(buffer.limit() - p);
|
||||||
}
|
} else buffer.rewind();
|
||||||
}
|
}
|
||||||
|
|
||||||
long xorshift64star(long s) {
|
long xorshift64star(long s) {
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* A simple backup mod for Fabric
|
||||||
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.szum123321.textile_backup.core.digest;
|
||||||
|
|
||||||
|
//import jdk.incubator.vector.*;
|
||||||
|
|
||||||
|
import net.szum123321.textile_backup.core.digest.BalticHash;
|
||||||
|
|
||||||
|
/*Mostly working XorSeaHash impl using SIMD. Should speed up calculation on most systems currently in use
|
||||||
|
|
||||||
|
It's actually slower. I tested it by comparing runtimes while hashing a directly opened FileInputStream.
|
||||||
|
My cpu is AMD Ryzen 5 3500U
|
||||||
|
|
||||||
|
There are two reasons I can think of: either vector construction simply takes so much time or jvm auto-vectorizes better than me
|
||||||
|
|
||||||
|
It's still probably far from being the slowest part of code, so I don't expect any major slowdowns
|
||||||
|
|
||||||
|
I will keep this code here for future work perhaps
|
||||||
|
*/
|
||||||
|
public class BalticHashSIMD extends BalticHash {
|
||||||
|
public BalticHashSIMD() { throw new UnsupportedOperationException(); } //For safety
|
||||||
|
|
||||||
|
/* private LongVector state = LongVector.fromArray(LongVector.SPECIES_256, IV, 0);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getValue() {
|
||||||
|
if(buffer.position() != 0) {
|
||||||
|
while(buffer.position() < buffer_limit) buffer.put((byte)0);
|
||||||
|
round();
|
||||||
|
}
|
||||||
|
|
||||||
|
long result = state.reduceLanesToLong(VectorOperators.XOR);
|
||||||
|
result ^= hashed_data_length;
|
||||||
|
|
||||||
|
return xorshift64star(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(byte[] data, int off, int len) {
|
||||||
|
int pos = off;
|
||||||
|
while(pos < len) {
|
||||||
|
int n = Math.min(len - pos, buffer_limit - buffer.position());
|
||||||
|
if(n == 32) {
|
||||||
|
var v = ByteVector.fromArray(ByteVector.SPECIES_256, data, pos).reinterpretAsLongs();
|
||||||
|
state = state.lanewise(VectorOperators.XOR, v);
|
||||||
|
state = xorshift64star(state);
|
||||||
|
} else {
|
||||||
|
System.arraycopy(data, pos, _byte_buffer, buffer.position(), n);
|
||||||
|
buffer.position(buffer.position() + n);
|
||||||
|
if(buffer.position() == buffer_limit) round();
|
||||||
|
}
|
||||||
|
pos += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed_data_length += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void round() {
|
||||||
|
var s = ByteVector.fromArray(ByteVector.SPECIES_256, _byte_buffer, 0).reinterpretAsLongs();
|
||||||
|
state = state.lanewise(VectorOperators.XOR, s);
|
||||||
|
state = xorshift64star(state);
|
||||||
|
|
||||||
|
int p = buffer.position();
|
||||||
|
|
||||||
|
if(p > buffer_limit) {
|
||||||
|
System.arraycopy(_byte_buffer, buffer_limit, _byte_buffer, 0, buffer.limit() - p);
|
||||||
|
buffer.position(buffer.limit() - p);
|
||||||
|
} else buffer.rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
LongVector xorshift64star(LongVector v) {
|
||||||
|
v = v.lanewise(VectorOperators.XOR, v.lanewise(VectorOperators.ASHR, 12));
|
||||||
|
v = v.lanewise(VectorOperators.XOR, v.lanewise(VectorOperators.LSHL, 25));
|
||||||
|
v = v.lanewise(VectorOperators.XOR, v.lanewise(VectorOperators.ASHR, 27));
|
||||||
|
v = v.lanewise(VectorOperators.MUL, 0x2545F4914F6CDD1DL);
|
||||||
|
return v;
|
||||||
|
}*/
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user