Pergunta

Estou trabalhando em um projeto que gera um número muito grande de seqüências de texto seqüenciais, em um loop muito apertado. Meu aplicativo faz uso pesado de extensões de instruções SIMD como SSE e MMX, em outras partes do programa, mas o gerador de chaves é C ++ simples.

A maneira como meu gerador de chaves funciona é eu tenho uma classe KeyGenerator, que contém uma única matriz de char que armazena a chave atual. Para obter a próxima chave, há uma função chamada "IncrementKey", que trata a string como um número, adicionando uma à string, carregando quando necessário.

Agora, o problema é que o keygen é um pouco de gargalo. É rápido, mas seria bom se fosse mais rápido. Um dos maiores problemas é que, quando estou gerando um conjunto de teclas seqüenciais a serem processadas usando meu código SSE2, tenho que ter o conjunto inteiro armazenado em uma matriz, o que significa que tenho que gerar e copiar sequencialmente 12 seqüências de strings em uma Array, um por um, como assim:

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

Então, como você geraria eficientemente essas seqüências de texto simples em ordem? Preciso de algumas idéias para ajudar a avançar isso. A simultaneidade seria legal; Como meu código está agora, cada chave sucessiva depende do anterior, o que significa que o processador não pode começar a funcionar na próxima chave até que a atual tenha sido completamente gerada.

Aqui está o código relevante para o gerador -chave:

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];
};

Caracteres.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;
};
Foi útil?

Solução

Bem .. em termos de desempenho, todos os novos/strcpy/strmp provavelmente estão te machucando muito mais do que o seu keygen.

ALoque sua memória em uma piscina maior de cada vez e depois use ponteiros dentro dela.

Com o Keygen, você deve evitar manter a abstração com vazamento de tecla única produzida, produza a quantidade ideal de cada vez. Possivelmente múltiplos maiores.

Em determinados intervalos, você pode realmente usar o SSE/MMX para produzir as teclas, pelo menos quando a string está alinhada e é divisível pelo seu comprimento de palavra SSE/MMX. Você também pode tentar prendê -lo com 0 e depois desviá -los se a string não estiver. Provavelmente não vale o esforço se você gerar apenas 16 por vez.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top