Как эффективно многопоточность алгоритма? - PullRequest
0 голосов
/ 12 июня 2018

Я иду прямо к делу.У меня есть этот код:

while (inputLength > 0)
{
    if (mode == MODE_AES_ENCRYPT)
        aesni_ecb_encrypt(ctx, input + shift, 16, output + shift);
    else if (mode == MODE_AES_DECRYPT)
        aesni_ecb_decrypt(ctx, input + shift, 16, output + shift);

    shift += 16;
    inputLength -= 16;
}

Он выполняет шифрование AES-ECB на одном 16-байтовом блоке на входе и сохраняет результат на выходе.Параметр ctx - это структура, которая содержит число раундов и подразделов для шифрования.

Теоретически можно шифровать AES-ECB, поэтому я попытался использовать многопоточность кода следующим образом:

typedef struct
{
    AES_Context* Ctx;

    unsigned char* input;
    unsigned char* output;

    _Bool done;
} threadInfos;

unsigned long WINAPI ThreadFunc(threadInfos* data)
{
    aes_ecb_encrypt(data->Ctx, data->input, data->output);

    data->done = 1;
}

while (inputLength > 0) 
{
    threadInfos info1; info1.done = 0; info1.Ctx = ctx;
    threadInfos info2; info2.done = 0; info2.Ctx = ctx;
    threadInfos info3; info3.done = 0; info3.Ctx = ctx;
    threadInfos info4; info4.done = 0; info4.Ctx = ctx;

    info1.input = (input + shift); info1.output = (output + shift);
    info2.input = (input + shift + 16); info2.output = (output + shift + 16);
    info3.input = (input + shift + 32); info3.output = (output + shift + 32);
    info4.input = (input + shift + 48); info4.output = (output + shift + 48);

    CreateThread(NULL, 0, ThreadFunc, &info1, 0, NULL);
    CreateThread(NULL, 0, ThreadFunc, &info2, 0, NULL);
    CreateThread(NULL, 0, ThreadFunc, &info3, 0, NULL);
    CreateThread(NULL, 0, ThreadFunc, &info4, 0, NULL);

    while (info1.done == 0 || info2.done == 0 || info3.done == 0 || info4.done == 0)
        ;

    shift += 64;
    inputLength -= 64;
}

и вот результаты в терминах скорости:

AES-ECB monothread vs. AES-ECB 4 threads

Вывод такой же, что означает, что моя многопоточностькажется, что работает, однако, это крайне неэффективно, поскольку он в 1000 раз медленнее ...

И вот мой вопрос.Как я могу использовать многопоточность шифрования в 4 или 8 потоках - в зависимости от возможностей процессора - но таким образом, чтобы он был быстрее, а не в 1000 раз медленнее?

1 Ответ

0 голосов
/ 12 июня 2018

Проблема в том, что вы создаете поток для выполнения одного блока алгоритма AES, а затем уничтожаете его снова.Как вы заметили, это в 1000 раз медленнее.Все ваше время тратится на создание и уничтожение потоков.

Что вам нужно сделать, это создать потоки один раз в начале, а затем заставить их работать как часть всех блоков.Например, пусть поток 0 выполняет все блоки с блоком% 4 == 0, поток 1 выполняет все блоки с блоком% 4 == 1 и т. Д.

Примечание: _Bool done; не является потокобезопасным.Например, на ARM ваш цикл ожидания может никогда не завершиться.

...