Многопоточное массовое копирование файлов

Модератор: Модераторы разделов

Аватара пользователя
AlphaGh0St
Сообщения: 41

Многопоточное массовое копирование файлов

Сообщение AlphaGh0St »

Всем привет!
Я написал не большую программку, которая копирует файлы из одной директории в другую.
Цель: продемонстрировать преимущества многопоточности.

Но вот результаты не радуют.
Копирую 445 файлов из одной директории в другую. Общий вес файлов - 842,9 метра.
Время выполнения программы:
1 поток:
real 1m16.085s
user 0m9.097s
sys 0m3.708s

2 потока:
real 1m17.756s
user 0m9.037s
sys 0m4.208s

3 потока:
real 1m27.259s
user 0m9.141s
sys 0m4.152s

Привожу исходный код:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <pthread.h>

#define MAX_NAME_LEN 100
#define MAX_DATA_LEN 100
#define THREADS_COUNT 3

struct fileAttr{
    char fileName[MAX_NAME_LEN];
    char dataFromFile[MAX_DATA_LEN];
};

struct dirAttr{
    DIR *dp;
    char copyFromDir[MAX_NAME_LEN];
    char copyToDir[MAX_NAME_LEN];
};

pthread_mutex_t blockMutex = PTHREAD_MUTEX_INITIALIZER;

void *beginCopy(void *);
void setPathAndFileName(char *, const char *, const char *);

int main(int argc, char *argv[]){
    struct dirAttr dAttr;
    pthread_t threads[THREADS_COUNT];
    int i;

    if(argc != 3){
        printf("Usage: %s <copy from dir> <copy to dir>\n", argv[0]);
        exit(1);
        }

    strncpy(dAttr.copyFromDir, argv[1], sizeof(dAttr.copyFromDir));
    strncpy(dAttr.copyToDir, argv[2], sizeof(dAttr.copyToDir));

    // Открываем директорию от куда копировать
    dAttr.dp = opendir(dAttr.copyFromDir);
    if(dAttr.dp == NULL){
        printf("[ERROR] Can't open dir %s\n", dAttr.copyFromDir);
        exit(1);
        }

    // Проверяем, существует ли директория, куда копировать
    // Если нет, создаём её
    if(opendir(dAttr.copyToDir) == NULL)
        if(mkdir(dAttr.copyToDir, S_IRUSR | S_IWUSR | S_IXUSR) == -1){
            printf("[ERROR] Can't make dir %s\n", dAttr.copyToDir);
            exit(1);
            }
        else
            printf("[INFO] Directory %s does not exists. I was make it\n", dAttr.copyToDir);

    for(i = 0; i < THREADS_COUNT; i++)
        if(pthread_create(&threads[i], NULL, beginCopy, (void *)&dAttr) != 0)
            perror("[ERROR] Can't create thread");

    for(i = 0; i < THREADS_COUNT; i++)
        pthread_join(threads[i], NULL);

    closedir(dAttr.dp);
    exit(0);
}

void *beginCopy(void *arg){
    struct fileAttr fAttr;
    struct dirent *dirp;
    FILE *copyFrom, *copyTo;

    struct dirAttr *dAttr = (struct dirAttr *)arg;

    pthread_mutex_lock(&blockMutex);
    // Просматриваем файлы в указанной директории
    while((dirp = readdir(dAttr->dp)) != NULL){
        if(!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
            continue;

        pthread_mutex_unlock(&blockMutex);

        printf("[INFO] thread id %u\n", pthread_self());
        fflush(stdout);

        setPathAndFileName(fAttr.fileName, dAttr->copyFromDir, dirp->d_name);
        printf("copy from: %s\n", fAttr.fileName);
        fflush(stdout);

        copyFrom = fopen(fAttr.fileName, "r");
        if(copyFrom == NULL){
            printf("[ERROR] Can't open file %s to read\n", fAttr.fileName);
            continue;
            }

        setPathAndFileName(fAttr.fileName, dAttr->copyToDir, dirp->d_name);
        printf("copy to  : %s ... ", fAttr.fileName);
        fflush(stdout);

        copyTo = fopen(fAttr.fileName, "w");
        if(copyFrom == NULL){
            printf("[ERROR] Can't open file %s to write\n", fAttr.fileName);
            continue;
            }

        // Копирование данных
        while(fgets(fAttr.dataFromFile, MAX_DATA_LEN, copyFrom) != NULL)
            fputs(fAttr.dataFromFile, copyTo);

        printf("Done\n\n");
        fflush(stdout);

        fclose(copyFrom);
        fclose(copyTo);
        }
}

void setPathAndFileName(char *fName, const char *path, const char *name){
    bzero(fName, sizeof(fName));
    strncpy(fName, path, MAX_NAME_LEN);
    strncat(fName, "/", 1);
    strncat(fName, name, MAX_NAME_LEN);
}


Мьютексом блокируется лишь получение имени последующего файла, но копирование не блокируется.
Системный монитор показывает, что во время работы программы, кол-во открытых ею файлов = кол-во потоков * 2, т.к. каждый поток открывает файл "копировать из" и "копировать в".

По идее, при увеличении числа потоков, программа должна выполняться быстрее, но на деле происходит иначе.
Подскажите, почему так?
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5403
ОС: Gentoo

Re: Многопоточное массовое копирование файлов

Сообщение /dev/random »

Вы ж с винтом работаете. Ему всё равно, один поток ему задания отправляет, или многие. Выполнять он их всё равно будет по очереди.
Спасибо сказали:
Аватара пользователя
AlphaGh0St
Сообщения: 41

Re: Многопоточное массовое копирование файлов

Сообщение AlphaGh0St »

А на каком примере тогда лучше продемонстрировать преимущества многопоточности?
Где от потоков действительно будет толк?
Спасибо сказали:
Аватара пользователя
Фантом
Сообщения: 460
ОС: openSUSE

Re: Многопоточное массовое копирование файлов

Сообщение Фантом »

AlphaGh0St писал(а):
13.11.2011 16:16
А на каком примере тогда лучше продемонстрировать преимущества многопоточности?
Где от потоков действительно будет толк?

Очевидно, там, где работа не предполагает доступа к устройствам чтения-записи (они почти никогда не могут быть многопоточными просто в силу технических ограничений) или этот доступ невелик. Т.е. разнообразный счет. В смысле "бытовых" задач - сжатие видео, обработка изображений и звука, архивация и т.п.
Спасибо сказали:
BIgAndy
Сообщения: 1923

Re: Многопоточное массовое копирование файлов

Сообщение BIgAndy »

AlphaGh0St писал(а):
13.11.2011 16:16
А на каком примере тогда лучше продемонстрировать преимущества многопоточности?
Где от потоков действительно будет толк?

Ой! Старо как мир: сортировка колец на "вавилонских башнях"... За одно и флаги выставлять научитесь..
Спасибо сказали:
Аватара пользователя
AlphaGh0St
Сообщения: 41

Re: Многопоточное массовое копирование файлов

Сообщение AlphaGh0St »

Дело в том, что мне для демонстрации нужен самый тривиальный пример рассчитанный на очень слабую аудиторию.
Полагаю, что "сортировка колец на "вавилонских башнях"", не покажется интересной никому.
Нужен самый простой пример, чтобы было понятно даже крестьянину. Что-то, чем пользуются все каждый день.

Идея с копированием файлов - это то, что нужно...если бы не технические ограничения.
Обработка видео, аудио, слишком сложно.
Нужно что-нибудь действительно простое и повседневное.
Спасибо сказали:
BIgAndy
Сообщения: 1923

Re: Многопоточное массовое копирование файлов

Сообщение BIgAndy »

AlphaGh0St писал(а):
13.11.2011 17:27
Дело в том, что мне для демонстрации нужен самый тривиальный пример рассчитанный на очень слабую аудиторию.
Полагаю, что "сортировка колец на "вавилонских башнях"", не покажется интересной никому.
Нужен самый простой пример, чтобы было понятно даже крестьянину. Что-то, чем пользуются все каждый день.

Что может быть проще? ВЫ не будете связаны ни с какими мьютексами, айнодами, флагами...
Спасибо сказали:
Аватара пользователя
Mifodix
Сообщения: 373
ОС: Fedora 17 x86_64

Re: Многопоточное массовое копирование файлов

Сообщение Mifodix »

AlphaGh0St писал(а):
13.11.2011 16:16
А на каком примере тогда лучше продемонстрировать преимущества многопоточности?
Где от потоков действительно будет толк?

Возьмите любой алгоритм перебора, который нравится, да оформите многопоточно:) Ту же быструю сортировку Хоара.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: Многопоточное массовое копирование файлов

Сообщение eddy »

AlphaGh0St писал(а):
13.11.2011 17:27
Нужен самый простой пример, чтобы было понятно даже крестьянину. Что-то, чем пользуются все каждый день.

Поиск красных глаз на фото?
Деконволюция.
В общем, огромное количество методов обработки изображений позволяют ускорить вычисления разбиением на потоки. Да даже построение преобразования Хафа (там, правда, придется использовать либо мьютексы, либо атомарные операции, либо положиться на "авось").

И да, про openmp вы не забыли?
Эта библиотека довольно-таки хорошо упрощает задачу параллелизации простеньких участков кода.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
aumit
Сообщения: 28

Re: Многопоточное массовое копирование файлов

Сообщение aumit »

AlphaGh0St писал(а):
13.11.2011 17:27
Нужно что-нибудь действительно простое и повседневное.

http://osll.fruct.org/wiki/doku.php?id=pap...rs:intel_mtl_en
Спасибо сказали:
Аватара пользователя
Voral
Сообщения: 1205
ОС: Debian Wheezy (amd64)

Re: Многопоточное массовое копирование файлов

Сообщение Voral »

Если хотите все же копирование и оперативки достаточно. Оговариваете, что узким место примера является диск, для исключения его влияния вы сначала в обоих вариантах загружаете файл в память, копируете в другую область, при необходимости скидываете. Отображаете время всех трех событий. Только второй шаг распараллеливаете. Хотя все равно могут обвинить в мухлевании :)

Я бы наверное взял например осветление фотографии. Ни каких "мудреных формул имени кого-то" - тупо берем пиксел светлим и все. Правда все равно лучше в память засунуть.
То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me © ?
Спасибо сказали:
Аватара пользователя
Voral
Сообщения: 1205
ОС: Debian Wheezy (amd64)

Re: Многопоточное массовое копирование файлов

Сообщение Voral »

Кстати. А не подойдет в качестве наглядного примера архивирование?

7zip умеет (см. в мане -m (Set compression Method) switch)
freearc http://www.freearc.org/ru/FreeArc040-rus.htm ключ -mN
Да и гугл говорит что у winrar есть встроенный бенчмарк с такой галкой.
То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me © ?
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Многопоточное массовое копирование файлов

Сообщение drBatty »

AlphaGh0St писал(а):
13.11.2011 15:34
Я написал не большую программку, которая копирует файлы из одной директории в другую.
Цель: продемонстрировать преимущества многопоточности.

при работе с диском больше всего времени занимает позиционирование, т.е. прыжки с дорожки на дорожку. Если копировать 3 файла по очереди, то таких прыжков почти нет, а если 3 файла сразу - то они будут постоянно (вообще-то должны после каждого блока в 4К, но у диска есть кеш, и потому он старается записать как можно больше блоков подряд, на одну дорожку. Но кеш небольшой, обычно метров 8..16).
А процессор вообще простаивает, ибо копирование идёт в обход процессора.
AlphaGh0St писал(а):
13.11.2011 16:16
А на каком примере тогда лучше продемонстрировать преимущества многопоточности?

нужна задача такая, что-бы
1. не требовалось частое обращение к HDD (т.к. он у вас один)
2. не требовалось частое обращение к памяти (т.к. она у вас одна)
Из-за пункта 2 не подходит задачи универсального сжатия - они много памяти жрут, и потоки будут стоять, и ждать своей очереди на память, сколько-бы их не было.
Из бытовых подходит только сжатие изображения/звука - там памяти немного надо, а считать много. Причём видео можно разделить на независимые потоки (звук в принципе тоже, но сложнее, и я не знаю, сделано-ли это в существующих кодеках).
Ну а вообще, в быту многоядерность не очень-то и нужна. Разве что если у вас Gentoo...

Voral писал(а):
14.11.2011 12:53
Кстати. А не подойдет в качестве наглядного примера архивирование?

нечестно. Пойдёт, но на алгоритме LZ77, где сжатие слабое(и памяти надо мало). На LZMA в этом нет никакого смысла. Можете попробовать для примера запустить парочку xz сразу. (xz не поддерживает многопоточность, похоже именно по этой причине).
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
AlphaGh0St
Сообщения: 41

Re: Многопоточное массовое копирование файлов

Сообщение AlphaGh0St »

Спасибо за советы, займусь делом.
Спасибо сказали:
Аватара пользователя
deadhead
Сообщения: 1913
Статус: zzz..z

Re: Многопоточное массовое копирование файлов

Сообщение deadhead »

Код: Выделить всё

cd linux
make defconfig
make -j4

?
[x] close
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: Многопоточное массовое копирование файлов

Сообщение Portnov »

Классические задачи, где хороша многопоточность, даже на одном ядре/процессоре — это задачи, в которых один поток занимается I/O, а другой — вычислениями. Ну, например, трёхпоточный аналог for F in **/*.txt; do gzip $F; done — один поток читает файлы, другой жмёт, третий пишет (ну или читает/пишет один поток, жмёт другой).
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали: