Avatar billede frodi Nybegynder
17. december 2004 - 14:23 Der er 13 kommentarer og
1 løsning

XOR af to bytes

er det nogen måde at XOR´re to bytes på, således at det er hurtigere end at XOR´re to integers

Dette stykke kode:

//bytes
byte a = 10;
byte b = 6;
byte c = 0;       
       
long start = System.currentTimeMillis();
       
for(int i = 0; i<50000000; i++)
{
    c = (byte)(a^b);
           
}       
long elapsedTimeMillis = System.currentTimeMillis()-start;       
System.out.println("Tid brugt for bytes: " + elapsedTimeMillis);
       
//int
int e = 10;
int f = 6;
int  g = 0;       
       
start = System.currentTimeMillis();
       
for(int i = 0; i<50000000; i++)
{
    g = e^f;
           
}       
elapsedTimeMillis = System.currentTimeMillis()-start;       
System.out.println("Tid brugt for int: " + elapsedTimeMillis);

er det dobbelt så hurtigt at XOR ´re to integer...

Er der en måde, hvor det er hurtigere at XOR to bytes ?
Avatar billede erikjacobsen Ekspert
17. december 2004 - 15:28 #1
Forklaringen er at mellemregninger sker med ints (32 bit), og at du i første udgave
skal konvertere fra byte til int, og tilbage - det tager lidt tid.

Skal du have lavet det på større datamængder på een gang kunne du overveje at gøre
det i C med JNI.

Jeg kender ingen anden metode.
Avatar billede frodi Nybegynder
17. december 2004 - 16:50 #2
Tak. Det løste ikke lige mit problem, men det hjalp mig videre. Er det fordi man arbejder på en 32-bit processor ?
Avatar billede frodi Nybegynder
17. december 2004 - 16:51 #3
sorry, hvordan giver jeg dig poing for dette ?
Avatar billede arne_v Ekspert
17. december 2004 - 21:43 #4
1) Medmindre du er igang med at kod ebrute force attack på en krypterings algoritme
  eller lignende så bør forskellen på XOR af int og byte ikke have signifikant
  betydning for den samlede performance.

2) Selv hvor XOR er vigtig så kan måde data hentes og processes på
  være mere vigtig end selve XOR.

Prøv f.eks. at køre dette eksempel:

public class XOR {
    private static final int LEN = 10000;
    private static final int REP = 10000;
    private static void testIAsimple(int[] ik, int[] ia, int[] ia2) {
        for(int i = 0; i < ia.length; i++) {
            ia2[i] = ik[i % ik.length] ^ ia[i];
        }
    }
    private static void testIAadvanced(int[] ik, int[] ia, int[] ia2) {
        int m = (ia.length / ik.length) * ik.length;
        for(int i = 0; i < m; i += ik.length) {
            for(int j = 0; j < ik.length; j++) {
                ia2[i + j] = ik[j] ^ ia[i + j];
            }
        }
        for(int i = m; i < ia.length; i++) {
            ia2[i] = ik[i % ik.length] ^ ia[i];
        }
    }
    private static void testBAsimple(byte[] bk, byte[] ba, byte[] ba2) {
        for(int i = 0; i < ba.length; i++) {
            ba2[i] = (byte) (bk[i % bk.length] ^ ba[i]);
        }
    }
    private static void testBAadvanced(byte[] bk, byte[] ba, byte[] ba2) {
        int m = (ba.length / bk.length) * bk.length;
        for(int i = 0; i < m; i += bk.length) {
            for(int j = 0; j < bk.length; j++) {
                ba2[i + j] = (byte) (bk[j] ^ ba[i + j]);
            }
        }
        for(int i = m; i < ba.length; i++) {
            ba2[i] = (byte) (bk[i % bk.length] ^ ba[i]);
        }
    }
    public static void main(String[] args) {
        int[] ik = { 1, 2, 3, 4, 5, 6 };
        int[] ia = new int[LEN];
        int[] ia2 = new int[LEN];
        for(int i = 0; i < LEN; i++) {
            ia[i] = i;
        }
        long t1 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            testIAsimple(ik, ia, ia2);
        }
        long t2 = System.currentTimeMillis();
        System.out.println("int[] simple : " + (t2 - t1) + " (" + ia2[0] + "," + ia2[LEN-1] + ")");
        long t3 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            testIAadvanced(ik, ia, ia2);
        }
        long t4 = System.currentTimeMillis();
        System.out.println("int[] advanced : " + (t4 - t3) + " (" + ia2[0] + "," + ia2[LEN-1] + ")");
        byte[] bk = { 1, 2, 3, 4, 5, 6 };
        byte[] ba = new byte[LEN];
        byte[] ba2 = new byte[LEN];
        for(int i = 0; i < LEN; i++) {
            ba[i] = (byte) i;
        }
        long t5 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            testBAsimple(bk, ba, ba2);
        }
        long t6 = System.currentTimeMillis();
        System.out.println("byte[] simple : " + (t6 - t5) + " (" + ba2[0] + "," + ba2[LEN-1] + ")");
        long t7 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            testBAadvanced(bk, ba, ba2);
        }
        long t8 = System.currentTimeMillis();
        System.out.println("byte[] advanced : " + (t8 - t7) + " (" + ba2[0] + "," + ba2[LEN-1] + ")");
    }
}
Avatar billede erikjacobsen Ekspert
18. december 2004 - 07:37 #5
det er ikke fordi du kører på en 32 bit processor, men fordi Java,
uanset processor arbejder på 32 bit tal i mellemresultater i
udtryk.

Tak, men jeg samler slet ikke på point.

Som Arne siger, så har det måske ikke den store betydning, så:
hvad skal du bruge det til?
Avatar billede frodi Nybegynder
18. december 2004 - 16:42 #6
Hej igen.
Jeg har implemeteret en krypteringsalgoritme, Rijndael. Den arbejder kun med tal fra 0-255, og for at peppe den op, ville jeg f.eks. gemme hvert tal i et byte i stedet for en int.

Jeg har brug for at XOR´re bytes, derfor vil evt. optimering, være at gemme 2*4 bytes i 2 ints, og derefter XOR disse, og bagefter læse 4 bytes fra resultatet igen fra Integeren. Dette giver en førøgning på 3X. har lige prøvet.

Tak for al hjælpen.

Kan C++ gemme mellemresultater i byte(8bit) ?

Troede ellers at problemet var ALU´en i processoren der konsekvent arbejder på 32-bit..
Avatar billede erikjacobsen Ekspert
18. december 2004 - 16:46 #7
Nu er det jo ikke sådan at et Java-program kan give to forskellige resultater,
afhængig af hvad processor den kører på. Beregningsmetoden er bestemt i
definitionen af Java.
Avatar billede arne_v Ekspert
18. december 2004 - 17:22 #8
Hvis du har data som bytes så kommer du til at bruge mere tid på at pakke ind
og ud af integers end du sparer ved at XOR'e 4 bytes i et hug.
Avatar billede frodi Nybegynder
18. december 2004 - 17:47 #9
Både nøgle og data er i bytes.
Jeg pakker
4 bytes fra nøglen ind i en Integer,
4 bytes fra nøglen ind i en Integer
or XOR derefter begge Integers. og læser resultatet tilbage i 4 bytes.

Dette er hurtigere end at XOR bytes enkeltvis, da resultatet af XOR(byte,byte) skal gemmes i en Integer, fordi da skal man igen type kaste til bytes..og dette tager længere tid..

Eller er jeg forkert på den ?
Avatar billede frodi Nybegynder
18. december 2004 - 17:48 #10
igen

4 bytes fra nøglen ind i en Integer,
4 bytes fra dataet ind i en Integer
Avatar billede arne_v Ekspert
18. december 2004 - 18:07 #11
Jeg tror at dte tager længere tid at lave byte[] -> int og int -> byte[] end
det tager at lave de konverteringer
Avatar billede arne_v Ekspert
18. december 2004 - 19:13 #12
Eksempel:

public class XOR2 {
    private static final int REP = 100000000;
    public static void main(String[] args) {
        int[] ik = { 1, 2, 64, 128 };
        int[] ia = { 128, 64, 2, 1 };
        int[] ia2 = new int[4];
        long t1 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            ia2[0] = ia[0] ^ ik[0];
            ia2[1] = ia[1] ^ ik[1];
            ia2[2] = ia[2] ^ ik[2];
            ia2[3] = ia[3] ^ ik[3];
        }
        long t2 = System.currentTimeMillis();
        System.out.println(ia2[0] + " " + ia2[1] + " " + ia2[2] + " " + ia2[3]);
        System.out.println("4 int : " + (t2 - t1));
        byte[] bk = { 1, 2, 64, -128 };
        byte[] ba = { -128, 64, 2, 1 };
        byte[] ba2 = new byte[4];
        long t3 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            ba2[0] = (byte) (ba[0] ^ bk[0]);
            ba2[1] = (byte) (ba[1] ^ bk[1]);
            ba2[2] = (byte) (ba[2] ^ bk[2]);
            ba2[3] = (byte) (ba[3] ^ bk[3]);
        }
        long t4 = System.currentTimeMillis();
        System.out.println(ba2[0] + " " + ba2[1] + " " + ba2[2] + " " + ba2[3]);
        System.out.println("4 byte : " + (t4 - t3));
        long t5 = System.currentTimeMillis();
        int ibk;
        int iba;
        int iba2;
        for(int i = 0; i < REP; i++) {
            ibk = (bk[0] << 24) | ((bk[1] << 16) & 0xFF0000) | ((bk[2] << 8) & 0xFF00) | (bk[3] & 0xFF);
            iba = (ba[0] << 24) | ((ba[1] << 16) & 0xFF0000) | ((ba[2] << 8) & 0xFF00) | (ba[3] & 0xFF);
            iba2 = ibk ^ iba;
            ba2[0] = (byte) (iba2 >> 24);
            ba2[1] = (byte) (iba2 >> 16);
            ba2[2] = (byte) (iba2 >> 8);
            ba2[3] = (byte) iba2;
        }
        long t6 = System.currentTimeMillis();
        System.out.println(ba2[0] + " " + ba2[1] + " " + ba2[2] + " " + ba2[3]);
        System.out.println("4 byte i 1 int variable key : " + (t6 - t5));
        ibk = (bk[0] << 24) | ((bk[1] << 16) & 0xFF0000) | ((bk[2] << 8) & 0xFF00) | (bk[3] & 0xFF);
        long t7 = System.currentTimeMillis();
        for(int i = 0; i < REP; i++) {
            iba = (ba[0] << 24) | ((ba[1] << 16) & 0xFF0000) | ((ba[2] << 8) & 0xFF00) | (ba[3] & 0xFF);
            iba2 = ibk ^ iba;
            ba2[0] = (byte) (iba2 >> 24);
            ba2[1] = (byte) (iba2 >> 16);
            ba2[2] = (byte) (iba2 >> 8);
            ba2[3] = (byte) (iba2 & 0xFF);
        }
        long t8 = System.currentTimeMillis();
        System.out.println(ba2[0] + " " + ba2[1] + " " + ba2[2] + " " + ba2[3]);
        System.out.println("4 byte i 1 int fixed key : " + (t8 - t7));
    }
}
Avatar billede frodi Nybegynder
19. december 2004 - 19:33 #13
jeg har lidt svært ved at gennemskye eksemplet.
Hvad er det lige de gør ?
Avatar billede arne_v Ekspert
19. december 2004 - 19:34 #14
4 byte -> 1 int
xor på int
1 int -> 4 byte
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester