Великий центральный диспетчер дает мне более медленное время выполнения - PullRequest
2 голосов
/ 20 декабря 2011

Итак, я на 99% уверен, что что-то не так понял, но дело в этом.

Я играл с Grand Central Dispatch и провел эксперимент по вычислению MD5-хешей. Я использую MacBook Air с i5, поэтому у меня есть 4 ядра. Это привело бы меня к мысли, что использование Grand Central Dispatch для вычисления хэшей будет примерно в 4 раза быстрее. Но, по некоторым причинам, это кажется медленнее.

Код ниже

Использование GCD

#include <stdio.h>
#include <time.h>
#import <CommonCrypto/CommonDigest.h>
#import <dispatch/dispatch.h>

int main (int argc, const char * argv[])
{

    int i,j,k,l,a;
    int num_chars = 4, total;
    clock_t start, end;
    double elap;

    printf("Calculating hashes for %d chars\n", num_chars);

    total = num_chars ^ 64;

    printf("Calculating %d hashes\n", total);

    dispatch_queue_t queue = dispatch_get_global_queue(0,0);
    dispatch_queue_t main = dispatch_get_main_queue();
    dispatch_group_t group = dispatch_group_create();

    start = clock();

   printf("Starting calculation queue\n");
   for(i=0;i<62;i++) {
        for(j=0;j<62;j++) {
            for(k=0;k<62;k++) {
                for(l=0;l<62;l++) {

                    dispatch_group_async(group, queue, ^{

                        char *letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                        char buffer[10];
                        char out[100];
                        unsigned char hash[16];

                        sprintf(buffer, "%c%c%c%c", letters[i], letters[j], letters[k], letters[l]);
                        CC_MD5(buffer, strlen(buffer), hash); 

                    });


                }
            }
        }
    }

   printf("Finished calculation queue\n");
   dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    end = clock();

    elap = ((double) end - start) / CLOCKS_PER_SEC;

    printf("Time taken  %2f\n", elap);
    return 0;
}

Скомпилируйте и запустите ...

gcc -o a.out main.c
./a.out
Calculating hashes for 4 chars
Calculating 68 hashes
Starting calculation queue
Finished calculation queue
Time taken  35.193133

Глядя на Activity Monitor, я вижу, что все 4 ядра максимально работают во время работы скрипта.

Теперь, закомментируйте отправку ....

#include <stdio.h>
#include <time.h>
#import <CommonCrypto/CommonDigest.h>
#import <dispatch/dispatch.h>

int main (int argc, const char * argv[])
{

    int i,j,k,l,a;
    int num_chars = 4, total;
    clock_t start, end;
    double elap;

    printf("Calculating hashes for %d chars\n", num_chars);

    total = num_chars ^ 64;

    printf("Calculating %d hashes\n", total);

    dispatch_queue_t queue = dispatch_get_global_queue(0,0);
    dispatch_queue_t main = dispatch_get_main_queue();
    dispatch_group_t group = dispatch_group_create();

    start = clock();

   printf("Starting calculation queue\n");
   for(i=0;i<62;i++) {
        for(j=0;j<62;j++) {
            for(k=0;k<62;k++) {
                for(l=0;l<62;l++) {

                    //dispatch_group_async(group, queue, ^{

                        char *letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                        char buffer[10];
                        char out[100];
                        unsigned char hash[16];

                        sprintf(buffer, "%c%c%c%c", letters[i], letters[j], letters[k], letters[l]);
                        CC_MD5(buffer, strlen(buffer), hash); 

                    //});




   }
        }
    }
}

printf("Finished calculation queue\n");
//dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

end = clock();

elap = ((double) end - start) / CLOCKS_PER_SEC;

printf("Time taken  %2f\n", elap);
return 0;
}

Скомпилируйте и запустите

gcc -o b.out main.c
./b.out
Calculating hashes for 4 chars
Calculating 68 hashes
Starting calculation queue
Finished calculation queue
Time taken  7.511273

Глядя на Activity Monitor, он показывает только 1 активное ядро ​​во время выполнения скрипта.

1 Ответ

4 голосов
/ 20 декабря 2011

Скорее всего, в диспетчере выполняется слишком мало работы, что не стоит накладных расходов, связанных с диспетчеризацией.Я бы попытался увеличить объем работы, выполняемой в каждой отправке.Я не имею понятия, поможет ли это, но попробуйте:

  1. Перемещение отправки вверх на несколько циклов, возможно, оберните цикл k или j внутри отправленного блокавместо этого, чтобы заставить его выполнять больше работы.

  2. Удалите вызовы sprintf и strlen.Фактически блок можно упростить до:

    static const char *letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    unsigned char hash[16];
    char buffer[4] = { letters[i], letters[j], letters[k], letters[l] };
    
    CC_MD5(buffer, sizeof buffer, hash);
    
...