Как я могу распараллелить несколько для цикла в OpenMP? - PullRequest
0 голосов
/ 30 ноября 2018

Я очень новичок в кодировании, и мне удалось собрать их из разных источников.Код работает в c, но я не могу начать работать в OpenMP.Я получаю ошибки, такие как получение правильного ключа один раз, а затем следующие четыре (4) или пять (5) попыток не генерируют правильный ключ.Любая помощь очень приветствуется.

Это мой код.

#include "omp.h"
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <string.h>
#include <time.h>

void handleErrors(void)
{
    ERR_print_errors_fp(stderr);
    abort();
}

int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
            unsigned char *iv, unsigned char *ciphertext)
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int ciphertext_len;

    if (!(ctx = EVP_CIPHER_CTX_new()))
        handleErrors();

    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
        handleErrors();

    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
        handleErrors();
    ciphertext_len += len;

    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

int main(void)

{
    int total_thread, thread_id;
    double start_time, end_time;
    start_time = omp_get_wtime();
    printf("Starting of the program, start_time = %f\n", start_time);

    /* A 128 bit key */
    unsigned char *key = (unsigned char *)"secret##########";

    /* A 128 bit IV */
    unsigned char *iv = (unsigned char *)"\x01\x02\x03\x04\x05\x06\x07\x08";

    /* Message to be encrypted */
    unsigned char *plaintext =
        (unsigned char *)"This is a really really top secret!";

    /* Buffer for ciphertext. Ensure the buffer is long enough for the
       ciphertext which may be longer than the plaintext, dependant on the
       * algorithm and mode */
    unsigned char ciphertext[128];
    unsigned char ciphertextnew[128];

#pragma omp parallel

    /* Encrypt the plaintext */
    encrypt(plaintext, strlen((char *)plaintext), key, iv, ciphertext);

    /* Do something useful with the ciphertext here */
    printf("Ciphertext is:\n");
    BIO_dump_fp(stdout, (const char *)ciphertext, 16);

    /*char pbuffer[1024];*/
    char password[17] = "################";
    char alphabet[] = "ectres";

    // int count;

#pragma omp parallel for

    for (int s = 0; s < 6; s++)
    {
        password[0] = alphabet[s];

        for (int t = 0; t < 6; t++)
        {
            password[1] = alphabet[t];

            for (int u = 0; u < 6; u++)
            {
                password[2] = alphabet[u];

                for (int v = 0; v < 6; v++)
                {
                    password[3] = alphabet[v];

                    for (int w = 0; w < 6; w++)
                    {
                        password[4] = alphabet[w];

                        for (int x = 0; x < 6; x++)
                        {
                            password[5] = alphabet[x];

                            encrypt(plaintext, strlen((char *)plaintext),
                                    password, iv, ciphertextnew);

                            if (strncmp(ciphertext, ciphertextnew, 16) == 0)
                            {
                                printf("\n%s", password);
                                printf("  Here is the correct key!\n\n");

                                end_time = omp_get_wtime();
                                total_thread = omp_get_num_threads();
                                thread_id = omp_get_thread_num();

                                printf("\nProgram start = %f\n", start_time);
                                printf("\nProgram end = %f\n", end_time);
                                printf("\n\nProgram runtime = %f seconds\n\n",
                                       end_time - start_time);

                                printf("\nTotal number of threads = %d\n",
                                       total_thread);
                                exit(0);
                            }

                            printf("\n%s", password);
                        }
                    }
                }
            }
        }
    }
    return 0;
}

// add padding to key
void pad(char *s, int length)
{
    int l;
    l = strlen(s); /* its length */
    while (l < length)
    {
        s[l] = '#'; /* insert a space */
        l++;
    }
    s[l] = '\0'; /* strings needs to be terminated in null */
}

1 Ответ

0 голосов
/ 30 ноября 2018

Как уже упоминалось @ Matthieu Brucher , у вас есть проблема с общим доступом к password.

Еще одна проблема - оператор exit(0);.Вы можете распараллеливать структурированные блоки только с одной точкой выхода внизу (т. Е. Более или менее блок операторов без каких-либо exit, return, goto ...).Таким образом, заявление о выходе не будет законным.Это кажется логичным: если поток достигает exit, что другие должны делать?Откуда они знают, что им тоже нужно выйти?

Однако существуют определенные директивы для отмены параллельного цикла, в значительной степени то, что мог бы сделать оператор break;.Директива omp cancel будет сигнализировать всем потокам о выходе из параллельного цикла или параллельной области.omp cancellation point - это точка, в которой потоки будут проверять, не было ли запрошено отмены.

Вам нужно будет найти, где должна быть поставлена ​​ точка отмены : слишком частое посещениезатраты с точки зрения накладных расходов (помещение его во внутренний цикл может быть неэффективным), но недостаточно часто означает, что поток может продолжать работать слишком долго, прежде чем осознает, что он должен выйти из цикла (помещение его в самый внешний цикл означает, чтотемы почти никогда не будут проверяться на отмену).

char password_found[17];
int flag_found=0;
#pragma omp parallel shared(password_found,flag_found)
{
    char password[17] = "################"; //this is a thread private variable

    // These will be done in parallel
    #pragma omp for collapse(3)
    for (int s = 0; s < 6; s++)
    for (int t = 0; t < 6; t++)
    for (int u = 0; u < 6; u++)
    {
        password[0] = alphabet[s];
        password[1] = alphabet[t];
        password[2] = alphabet[u];

        // For every s,t,u, a single thread will loop through these
        for (int v = 0; v < 6; v++)
        for (int w = 0; w < 6; w++)
        for (int x = 0; x < 6; x++) 
        {
            password[3] = alphabet[v];
            password[4] = alphabet[w];
            password[5] = alphabet[x];

            encrypt(plaintext, strlen((char *)plaintext),
                    password, iv, ciphertextnew);

            if (strncmp(ciphertext, ciphertextnew, 16) == 0)
            {
                printf("\n%s", password);
                printf("  Here is the correct key!\n\n");

                flag_found=1;
                strcpy(password_found,password); // Copy thread-private copy to shared variable

                // Now, signal everyone to stop
                #pragma omp cancel parallel
            }

            printf("\n%s is bad", password);

        } // end inner group of loops

        // Threads will check here is they should stop
        #pragma omp cancellation point parallel
    } // end of the outer group of loops
} // end of parallel region

 // Do something now //
if (flag_found){
    printf("\nThe password is %s\n",password_found);
    return 0;
}else{
    printf("Password not found\n");
    return 1;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...