如何在OpenMP中并行化多个for循环?

时间:2018-11-30 16:28:49

标签: c openmp

我对编码非常陌生,并且设法从不同的来源将它们组合在一起。代码在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 :(得分:0)

@Matthieu Brucher 所述,您在共享password时遇到了问题。

另一个是exit(0);语句。您只能并行化结构化块,使其底部具有单个出口点(即,或多或少没有任何exitreturngoto ...的语句块)。因此,退出声明将不合法。似乎合乎逻辑:如果某个线程命中了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;
}