Ложный обмен в многопоточности - PullRequest
0 голосов
/ 06 мая 2020

Следующий код работает медленнее, чем я увеличиваю NTHREADS . Зачем использовать больше потоков, чтобы программа работала медленнее? Есть ли способ исправить? Кто-то сказал, что речь идет о ложном совместном использовании , но я не совсем понимаю эту концепцию.

Программа в основном вычисляет сумму от 1 до 100000000. Идея использования многопоточности заключается в разделении списка номеров на несколько блоков и параллельно вычисляйте сумму каждого блока, чтобы ускорить расчет.

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

#define LENGTH 100000000
#define NTHREADS 2
#define NREPEATS 10
#define CHUNCK (LENGTH / NTHREADS)

typedef struct {
        size_t id;
        long *array;
        long result;
} worker_args;

void *worker(void *args) {

        worker_args *wargs = (worker_args*) args;

        const size_t start = wargs->id * CHUNCK;
        const size_t end = wargs->id == NTHREADS - 1 ? LENGTH : (wargs->id+1) * CHUNCK;

        for (size_t i = start; i < end; ++i) {
                wargs->result += wargs->array[i];
        }

        return NULL;
}

int main(void) {

        long* numbers = malloc(sizeof(long) * LENGTH);
        for (size_t i = 0; i < LENGTH; ++i) {
                numbers[i] = i + 1;
        }

        worker_args *args = malloc(sizeof(worker_args) * NTHREADS);

            for (size_t i = 0; i < NTHREADS; ++i) {
                    args[i] = (worker_args) {
                            .id = i,
                            .array = numbers, 
                            .result = 0
                    };
            }

            pthread_t thread_ids[NTHREADS];

            for (size_t i = 0; i < NTHREADS; ++i) {
                    pthread_create(thread_ids+i, NULL, worker, args+i);
            }

            for (size_t i = 0; i < NTHREADS; ++i) {
                    pthread_join(thread_ids[i], NULL);
            }

            long sum = 0;

            for (size_t i = 0; i < NTHREADS; ++i) {
                sum += args[i].result;
            }

            printf("Run %2zu: total sum is %ld\n", n, sum);

        free(args);
        free(numbers);
}

1 Ответ

4 голосов
/ 06 мая 2020

Зачем использовать большее количество потоков, чтобы программа работала медленнее?

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

Ваши потоки выполняют только простую сумму, которая не так уж и дорога. Также учтите, что переход, например, от 10 до 11 потоков, не сильно меняет рабочую нагрузку на поток.

10 потоков -> 10000000 сум на поток

11 потоков -> 9090909 сум на поток

Накладные расходы на создание дополнительного потока могут превышать «сохраненную рабочую нагрузку» на поток.

На моем P C программа выполняется менее чем за 100 миллисекунд. Многопоточность не стоит проблем.

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

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

ложное совместное использование

да, «ложное совместное использование» может повлиять на производительность многопоточной программы, но я сомневаюсь, что это настоящая проблема в вашем случае.

«ложное совместное использование» - это то, что происходит в (некоторых) системах кеширования, когда два потока (или, скорее, два ядра) записывают в две разные переменные, принадлежащие одной и той же строке кеша . В таких случаях два потока / ядра соревнуются за владение строкой кеша (для записи), и, следовательно, им придется обновлять sh память и кеш снова и снова. Это плохо для производительности.

Как я уже сказал - я сомневаюсь, что это ваша проблема. Умный компилятор сделает вашу l oop исключительно с использованием регистров ЦП и только в конце будет записывать в память. Вы можете проверить дизассемблирование вашего кода, чтобы убедиться, что это так. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...