我必须实现以下算法,该算法将通过爬山在特定密码的密码分析中运行几十亿次。 该算法产生标准字母{A,B,C,...,Y,Z}的排列,其中K为7个相同字母的字母,如下所示:
实际上我需要在解密代码中进行逆置换。 我的代码实现了一个链接列表,用于跳过使用过的字母。 它在基数0,所以A = 0,... Z = 25并返回逆置换Pinv(i)= j意味着字母i在位置j。
#define ALPHALEN 26
void KeyToPermut(int *K, int * Pinv);
int previnit[ALPHALEN], prev[ALPHALEN], nextinit[ALPHALEN], next[ALPHALEN];
int main() {
int l, Pinv[ALPHALEN], K[7] = { 8, 13, 6, 23, 13, 3, 12 }, P[ALPHALEN];
// precalculate links between letters, ordered right to left , from Z to A
for (l = 0; l < ALPHALEN; l++) {
previnit[l] = l + 1; // prev[A] = B
if (previnit[l] >= ALPHALEN) previnit[l] -= ALPHALEN; // prev[Z] = A
nextinit[l] = l - 1; // next[B] = A
if (nextinit[l] < 0) nextinit[l] += ALPHALEN; // next[A] = Z
}
KeyToPermut(K, Pinv); // this is the code to be optimized
for (l = 0; l < ALPHALEN; l++) P[Pinv[l]] = l; // calculate direct permutation
for (l = 0; l < ALPHALEN; l++) printf("%c", P[l] + 65);
printf("\n");
}
void KeyToPermut(int *K, int * Permut) {
int l, keyptr=0, cnt=0, p=0;
// copy prev[] and next[] from precalculated arrays previnit[] and nextinit[]
for (l = 0; l < ALPHALEN; l++) {
prev[l] = previnit[l];
next[l] = nextinit[l];
}
while (1) {
for (l = 0; l <= K[keyptr] % (ALPHALEN-cnt); l++) p = next[p];
Permut[p] = cnt++;
if (cnt < ALPHALEN)
{
prev[next[p]] = prev[p]; // link previous and next positions
next[prev[p]] = next[p];
keyptr++;
if (keyptr >= 7) keyptr = 0; // re-use K1 after K7
}
else
break;
}
}
我有两个问题:
我使用的是VS2013和C,项目的其他部分都是CUDA代码。 (x64平台)
感谢您的关注。
背景信息:密码使用的加密方案使用长度为7的4个密钥K.因此,用于查找纯文本的理论密钥空间是26 ^ 28,即131位。该方法可以使用其他密钥长度:1到25之间的任何值都可以使用。
答案 0 :(得分:0)
如何优化KeyToPermut中的代码?剖析器显然 表示链接中的for循环是瓶颈。 可能有一种避免链表的方法......?
我没有找到一个更好的方法来避免链表,但我们可以单独使用而不是双重链接,因为所需的先前位置可以从for循环的最后一次迭代中获得。
void KeyToPermut(int *K, int *Permut)
{
int l, keyptr=0, cnt=0, p=0, prev;
// copy next[] from precalculated array nextinit[]
for (l = 0; l < ALPHALEN; l++) next[l] = nextinit[l];
while (1)
{
for (l = 0; l <= K[keyptr] % (ALPHALEN-cnt); l++) prev = p, p = next[p];
Permut[p] = cnt++;
if (cnt < ALPHALEN)
{
next[prev] = next[p]; // link previous to next position
p = prev;
keyptr++;
if (keyptr >= 7) keyptr = 0; // re-use K1 after K7
}
else
break;
}
}
这节省了约10%的函数运行时间。