题
我正在研究一个项目,该项目在非常紧密的循环中生成大量的顺序文本字符串。我的应用程序在程序的其他部分中大量使用SIMD指令集的扩展名(例如SSE和MMX),但是密钥生成器是普通的C ++。
我的密钥生成器的工作方式是我有一个键机类,该类容纳一个存储当前密钥的单个字符阵列。为了获取下一个键,有一个称为“ cormementkey”的函数,它将字符串视为一个数字,将一个函数添加到字符串中,并在必要时携带。
现在,问题是,Keygen有点像瓶颈。快速,但是如果更快的话,那会很好。最大的问题之一是,当我生成一组使用我的SSE2代码处理的顺序键时,我必须将整个集合存储在一个数组中,这意味着我必须顺序生成并复制12个字符串阵列,一个人,像这样:
char* keys[12];
for(int i = 0; i < 12; i++)
{
keys[i] = new char[16];
strcpy(keys[i], keygen++);
}
那么,您将如何有效地按顺序生成这些明文字符串呢?我需要一些想法来帮助发展这一点。并发会很好。由于我现在的代码现在,每个连续的密钥都取决于上一个密钥,这意味着处理器在当前密钥完全生成之前无法开始在下一个密钥上工作。
这是与密钥生成器相关的代码:
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];
};
tamemet.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;
};
解决方案
好..在性能方面,所有新的/strcpy/strmp都可能比钥匙棒更伤害您。
一次将内存分配在较大的池中,然后在其中使用指针。
使用KeyGen,您应该避免坚持产生的单键泄漏的抽象,而是一次产生最佳量。可能是较大的倍数。
在某些时间间隔内,您实际上可以使用SSE/MMX生成键,至少当字符串对齐并被SSE/MMX单词长度排除时。您也可以尝试将其用0键入0,然后如果字符串不在,则将它们移开。如果您一次只生成16个,那么可能真的不值得付出努力。
不隶属于 StackOverflow