Многопоточное программирование для memcpy

Я делаю задачу оптимизации для функции memcpy, я нашел эту ссылку здесь. Как повысить производительность memcpy

Поскольку я не знаком с многопоточным программированием, я не знаю, как вставить приведенные ниже коды в исходную основную функцию? Как изменить коды в исходном вопросе в многопоточный проект memcpy? Я имею в виду, как создать полный проект для этого многопоточного memcpy проекта. Где места для вставки таких функций, как startCopyThreads, stopCopyThreads или mt_memcpy, в исходную основную функцию?

#define NUM_CPY_THREADS 4

HANDLE hCopyThreads[NUM_CPY_THREADS] = {0};
HANDLE hCopyStartSemaphores[NUM_CPY_THREADS] = {0};
HANDLE hCopyStopSemaphores[NUM_CPY_THREADS] = {0};
typedef struct
{
    int ct;
    void * src, * dest;
    size_t size;
} mt_cpy_t;

mt_cpy_t mtParamters[NUM_CPY_THREADS] = {0};

DWORD WINAPI thread_copy_proc(LPVOID param)
{
    mt_cpy_t * p = (mt_cpy_t * ) param;

    while(1)
    {
        WaitForSingleObject(hCopyStartSemaphores[p->ct], INFINITE);
        memcpy(p->dest, p->src, p->size);
        ReleaseSemaphore(hCopyStopSemaphores[p->ct], 1, NULL);
    }

    return 0;
}

int startCopyThreads()
{
    for(int ctr = 0; ctr < NUM_CPY_THREADS; ctr++)
    {
        hCopyStartSemaphores[ctr] = CreateSemaphore(NULL, 0, 1, NULL);
        hCopyStopSemaphores[ctr] = CreateSemaphore(NULL, 0, 1, NULL);
        mtParamters[ctr].ct = ctr;
        hCopyThreads[ctr] = CreateThread(0, 0, thread_copy_proc, &mtParamters[ctr], 0,     NULL); 
}

    return 0;
}

void * mt_memcpy(void * dest, void * src, size_t bytes)
{
    //set up parameters
    for(int ctr = 0; ctr < NUM_CPY_THREADS; ctr++)
    {
        mtParamters[ctr].dest = (char *) dest + ctr * bytes / NUM_CPY_THREADS;
        mtParamters[ctr].src = (char *) src + ctr * bytes / NUM_CPY_THREADS;
        mtParamters[ctr].size = (ctr + 1) * bytes / NUM_CPY_THREADS - ctr * bytes /     NUM_CPY_THREADS;
    }

    //release semaphores to start computation
    for(int ctr = 0; ctr < NUM_CPY_THREADS; ctr++)
        ReleaseSemaphore(hCopyStartSemaphores[ctr], 1, NULL);

    //wait for all threads to finish
    WaitForMultipleObjects(NUM_CPY_THREADS, hCopyStopSemaphores, TRUE, INFINITE);

    return dest;
}

int stopCopyThreads()
{
    for(int ctr = 0; ctr < NUM_CPY_THREADS; ctr++)
    {
        TerminateThread(hCopyThreads[ctr], 0);
        CloseHandle(hCopyStartSemaphores[ctr]);
        CloseHandle(hCopyStopSemaphores[ctr]);
    }
    return 0;
}

person zjluoxiao    schedule 21.03.2013    source источник
comment
Куда ты идешь с этим? Вы надеетесь улучшить производительность memcpy() за счет использования нескольких потоков?   -  person NPE    schedule 21.03.2013
comment
@NPE Да, это то, что я хочу.   -  person zjluoxiao    schedule 21.03.2013
comment
По сути, вы бы вызвали mt_memcpy из своей основной функции. Как бы то ни было, это вряд ли на самом деле увеличит скорость memcpy. Накладные расходы на семафоры и потоки намного превышают стоимость большинства операций memcpy. Но вы должны измерить его, прежде чем использовать в своем коде.   -  person Missaka Wijekoon    schedule 21.03.2013
comment
Тема, на которую вы ссылаетесь, датируется 2010 годом, она очень старая :) Не ожидайте, что вы получите эти вещи быстрее без глубоких знаний вашей архитектуры (ОС и процессора). Обычно это довольно оптимизировано на современных системах, и это трудно превзойти. В любом случае это зависит от пропускной способности вашей памяти, а не от времени обработки.   -  person Jens Gustedt    schedule 21.03.2013
comment
@Missaka Wijekoon Как автор этого вопроса мог получить такой результат: 1 поток: 1826 МБ/сек 2 потока: 3118 МБ/сек 3 потока: 4121 МБ/сек. Вы имеете в виду, что мне нужно заменить функцию memcpy в исходной основной функции на mt_memcpy? И где место для вставки функций startCopyThreads или stopCopyThreads? Мне просто нужен полный проект, чтобы получить результат для нескольких потоков. Спасибо   -  person zjluoxiao    schedule 21.03.2013
comment
@Jens Gustedt Но как автор мог получить такой результат, как: 1 поток: 1826 МБ/сек 2 потока: 3118 МБ/сек 3 потока: 4121 МБ/сек. Мне просто нужно, как изменить исходные коды и получить такой результат теста   -  person zjluoxiao    schedule 21.03.2013
comment
Другие вопросы имеют очень специфическую аппаратную конфигурацию: Детали аппаратного обеспечения: AMD Magny Cours — 4-кратное восьмиядерное ядро ​​128 ГБ DDR3, что, вероятно, влияет на результат. Запуск потока на отдельном ядре даст вам отдельный контроллер памяти на этом оборудовании, но не на наших обычных настольных компьютерах.   -  person Bo Persson    schedule 21.03.2013
comment
На большинстве архитектур однопоточный memcpy уже ограничен чистой пропускной способностью памяти, а не скоростью выполнения. Возможно, есть какие-то экзотические или мистические сборки, в которых многие потоки будут работать лучше в некоторых ситуациях, но существует много реальных архитектур, где они будут работать значительно хуже (NUMA). Просто не делай этого.   -  person Damon    schedule 21.03.2013


Ответы (1)


Многое зависит от архитектуры и ОС.

С одним процессором:

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

С многоядерным:

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

person Plasma    schedule 21.03.2013
comment
Однако, если в вашем процессоре есть модуль SIMD, использование этих инструкций определенно поможет в улучшении, и вам не нужно использовать потоки. - person Plasma; 21.03.2013
comment
Знаете ли вы, как изменить коды в ссылке, которую я упомянул выше, чтобы получить результат, например: 1826 МБ/сек 2 потока: 3118 МБ/сек 3 потока: 4121 МБ/сек? Я имею в виду, что даже я не могу получить тот же результат. Я могу проверить, работает ли этот многопоточный метод на моем процессоре i7 или нет. - person zjluoxiao; 21.03.2013