2016-05-29 3 views
1

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

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <time.h> 
#include <pthread.h> 

#define WIDTH 20000 
pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; 

struct split { // sizeof(split) = 24 
    int start; 
    int end; 
    int* matrix; 
    int i; 
    char padding[64 - 24]; //Padding the private sum variables  forces them into separate cache lines and removes false sharing. Assume cache line is 64 bytes 
}; 

int ran(){ 
    return rand() % 21; 
} 
int* createBigMatrix(){ 
    int* a = malloc(sizeof(int)* WIDTH * WIDTH); 
    for (int i = 0; i < WIDTH * WIDTH; i ++){ 
     a[i] = ran(); // fill up the matrix with random numbers 
    } 
    return a; 
} 
static int finalSum; 
void* partialSum(void* arg){ 
    struct split* a = arg; 
    int totalSum = 0; // create local variable 
    int i; 
    for (i = a->start; i <= a->end; i ++){ 
     totalSum += a->matrix[i]; 
    } 
    pthread_mutex_lock(&mylock); 
    finalSum += totalSum; // critical section 
    pthread_mutex_unlock(&mylock); 
    free(a); 

    return 0; 
} 
int main(){ //-294925289 
    int useMultiThreads = 1; // there is no difference between using one thread or 4 therads 
    finalSum = 0; 
    pthread_t thread_ids[4]; 
    // i want a square matrix of npages width 
    int* c = createBigMatrix(); 

    printf("%lu\n", sizeof(struct split)); 
    if (useMultiThreads){ 
     // split the tasks evenly amoung 4 threads 
     // since there are 20,000x20,000, there must be 400,000,000 cells 
     int start[] = {0, 100000000, 200000000, 300000000}; 
     int end[] = {99999999, 199999999, 299999999, 399999999}; 
     // calculate sum 
     for (int i = 0; i < 4; i ++){ 
      struct split* a = malloc(sizeof(struct split)); 
      a->start = start[i]; 
      a->end = end[i]; 
      a->matrix = c; 
      pthread_create(thread_ids + i, NULL, partialSum, a); 
     } 

     for (int i = 0; i < 4; i ++){ // join em up 
      pthread_join(thread_ids[i], NULL); 
     } 
    } 
    else { // use single thread 
     for (int i = 0; i <= 399999999; i ++){ 
      finalSum += c[i]; 
     } 
    } 

    printf("total sum is %d\n", finalSum); 
/* 
    real 0m4.871s 
    user 0m4.844s 
    sys  0m0.392s 
*/ 
    free(c); 
    return 0; 
} 
+2

По-видимому, не существует большого объема для ложного обмена, поскольку матричные индексы, используемые потоками, не перекрываются, и, в любом случае, добавление параметра struct не помогло бы. Как вы измеряете время, потраченное на эту сумму? Мне кажется, что общая производительность этого процесса будет заключаться в создании и загрузке огромного массива до начала суммирования? –

+1

Будьте осторожны с вашими индексами, 'int' окончательно не соответствует типу для больших матриц. Также укажите использование 'a->' из вашего цикла 'for'. Компилятор не может знать, может ли '* a' изменяться под капотом, поэтому он должен перезагружаться на каждой итерации. Вы можете изменить '' '' '' 'ограниченный '', но проще просто загрузить значения (границы и матрицу) в локальные переменные и использовать их внутри цикла. –

ответ

0

Я не вижу вообще обивку вашего struct должен делать с выполнением коды. Реальные данные находятся в матрице, на которую указывают.

В чем вас беспокоит отсутствие ускорения, возможно, это связано с тем, что ваш код полностью связан с памятью. То есть для выполнения суммы данные должны извлекаться из памяти через шину памяти. (Ваша матрица слишком велика, чтобы соответствовать кешу). То есть, ваши вычисления связаны пропускной способностью вашей шины памяти, которая разделяется всеми вашими ядрами.

Также обратите внимание, что в вашем коде не преобладает выполнение суммы, а по звонкам ran(), которые находятся в последовательной части программы.

Смежные вопросы