代码之家  ›  专栏  ›  技术社区  ›  jakogut

同时生成顺序键

  •  1
  • jakogut  · 技术社区  · 14 年前

    我正在做一个项目,这个项目在一个非常紧密的循环中生成大量连续的文本字符串。我的应用程序在程序的其他部分大量使用SIMD指令集扩展,如SSE和MMX,但密钥生成器是普通C++。

    我的密钥生成器的工作方式是我有一个keyGenerator类,它包含一个存储当前密钥的char数组。为了获得下一个键,有一个名为“incrementkey”的函数,它将字符串视为一个数字,在字符串中添加一个数字,并在必要时进行携带。

    现在,问题是,keygen有点像瓶颈。它很快,但如果快一点就好了。最大的问题之一是,当我生成一组要使用SSE2代码处理的顺序键时,我必须将整个组存储在一个数组中,这意味着我必须依次生成12个字符串并将其复制到一个数组中,就像这样:

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

    那么,如何有效地按顺序生成这些纯文本字符串呢?我需要一些想法来推动这一进程。并发性很好;因为我的代码现在是这样的,每个连续的键都依赖于前一个键,这意味着在当前键完全生成之前,处理器无法开始处理下一个键。

    以下是与密钥生成器相关的代码:

    密钥生成器

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

    特征集

    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;
    };
    
    1 回复  |  直到 9 年前
        1
  •  1
  •   Pasi Savolainen    14 年前

    好。。从性能上讲,所有新的/strcpy/strmp可能对你的伤害要比你的keygen大得多。

    一次在较大的池中分配内存,然后在池中使用指针。

    对于keygen,您应该避免坚持对生成的单个密钥进行泄漏抽象,而是一次生成最佳数量的密钥。可能是更大的倍数。

    在某些间隔上,您实际上可以使用sse/mmx生成键,至少当字符串对齐并且可以被sse/mmx字长整除时。你也可以试着用0填充它,如果字符串不是0,则将它们移走。如果一次只生成16个,那么这可能不太值得。