Frage

Ich arbeite an einem Projekt, das in einer sehr engen Schleife eine sehr große Anzahl von sequentiellen Textketten generiert. Meine Anwendung nutzt die SIMD -Befehlssatzerweiterungen wie SSE und MMX in anderen Teilen des Programms stark, aber der Schlüsselgenerator ist einfach C ++.

Die Art und Weise, wie mein Schlüsselgenerator funktioniert, ist, dass ich eine Keygenerator -Klasse habe, die ein einzelnes Zeichen -Array enthält, das den aktuellen Schlüssel speichert. Um den nächsten Schlüssel zu erhalten, gibt es eine Funktion namens "IncrementKey", die die Zeichenfolge als Zahl behandelt und die Zeichenfolge bei Bedarf eine hinzufügt.

Das Problem ist nun, der Keygen ist ein bisschen ein Engpass. Es ist schnell, aber es wäre schön, wenn es schneller wäre. Eines der größten Probleme ist, dass ich, wenn ich eine Reihe von sequentiellen Schlüssel generiere, die mit meinem SSE2 -Code verarbeitet werden sollen Array, eins nach dem anderen, wie SO:

char* keys[12];
for(int i = 0; i < 12; i++)
{
    keys[i] = new char[16];
    strcpy(keys[i], keygen++);
}

Wie würden Sie diese Klartext -Zeichenfolgen effizient in Ordnung erzeugen? Ich brauche einige Ideen, um dies mitzunehmen. Parallelität wäre schön; Da mein Code im Moment ist, hängt jeder aufeinanderfolgende Schlüssel von der vorherigen ab, was bedeutet, dass der Prozessor nicht mit der Arbeit an der nächsten Schlüssel beginnen kann, wenn die aktuelle vollständig generiert wurde.

Hier ist der Code, der für den Schlüsselgenerator relevant ist:

Keygenerator.h

class keyGenerator
{

public:

    keyGenerator(unsigned long long location, characterSet* charset)
            : location(location), charset(charset)
    {           
        for(int i = 0; i < 16; i++)
            key[i] = 0;

        charsetStr = charset->getCharsetStr();
        integerToKey();
    }

    ~keyGenerator()
    {
    }

    inline void incrementKey()
    {
        register size_t keyLength = strlen(key);

        for(register char* place = key; place; place++)
        {
            if(*place == charset->maxChar)
            {
                // Overflow, reset char at place
                *place = charset->minChar;

                if(!*(place+1))
                {
                    // Carry, no space, insert char
                    *(place+1) = charset->minChar;
                    ++keyLength;

                    break;
                }
                else
                {
                    continue;
                }
            }
            else
            {
                // Space available, increment char at place
                if(*place == charset->charSecEnd[0]) *place = charset->charSecBegin[0];
                else if(*place == charset->charSecEnd[1]) *place = charset->charSecBegin[1];

                (*place)++;

                break;
            }
        }
    }

    inline char* operator++() // Pre-increment
    {
            incrementKey();
            return key;
    }

    inline char* operator++(int) // Post-increment
    {
            memcpy(postIncrementRetval, key, 16);
            incrementKey();

            return postIncrementRetval;
    }

    void integerToKey()
    {
        register unsigned long long num = location;

        if(!num)
        {
            key[0] = charsetStr[0];
        }
        else
        {
            num++;

            while(num)
            {
                num--;
                unsigned int remainder = num % charset->length;
                num /= charset->length;

                key[strlen(key)] = charsetStr[remainder];
            }
        }
    }

    inline unsigned long long keyToInteger()
    {
        // TODO
        return 0;
    }

    inline char* getKey()
    {
        return key;
    }

private:

    unsigned long long location;

    characterSet* charset;
    std::string charsetStr;

    char key[16];

    // We need a place to store the key for the post increment operation.
    char postIncrementRetval[16];
};

CharakturenSet.h

struct characterSet
{
    characterSet()
    {
    }

    characterSet(unsigned int len, int min, int max, int charsec0, int charsec1, int charsec2, int charsec3)
    {
        init(length, min, max, charsec0, charsec1, charsec2, charsec3);
    }

    void init(unsigned int len, int min, int max, int charsec0, int charsec1, int charsec2, int charsec3)
    {
        length = len;
        minChar = min;
        maxChar = max;

        charSecEnd[0] = charsec0;
        charSecBegin[0] = charsec1;
        charSecEnd[1] = charsec2;
        charSecBegin[1] = charsec3;
    }

    std::string getCharsetStr()
    {
        std::string retval;

        for(int chr = minChar; chr != maxChar; chr++)
        {
            for(int i = 0; i < 2; i++) if(chr == charSecEnd[i]) chr = charSecBegin[i];
            retval += chr;
        }

        return retval;
    }

    int minChar, maxChar;

    // charSec = character set section
    int charSecEnd[2], charSecBegin[2];

    unsigned int length;
};
War es hilfreich?

Lösung

Naja .. In Bezug auf die Leistung haben Sie alle neuen/strcpy/strmp wahrscheinlich viel mehr als Ihr Keygen.

Weisen Sie Ihren Speicher jeweils in einem größeren Pool zu und verwenden Sie dann Zeiger darin.

Mit Keygen sollten Sie es vermeiden, sich an die undichte Abstraktion des erzeugten einzelnen Schlüssels zu halten und stattdessen die optimale Menge produzieren zu können. Möglicherweise größere Vielfachen.

In bestimmten Intervallen können Sie tatsächlich SSE/MMX verwenden, um die Schlüssel zu erzeugen, zumindest wenn die Zeichenfolge ausgerichtet ist und durch Ihre SSE/MMX -Wortlänge teilbar ist. Sie könnten auch versuchen, es mit 0er zu padieren und sie dann wegzuschieben, wenn die Saite nicht der Fall ist. Es ist wahrscheinlich nicht wirklich die Mühe wert, wenn Sie nur 16 gleichzeitig generieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top