Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/26: Рейтинг темы: голосов - 26, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 19.02.2019
Сообщений: 5

Распараллеливание с помщью потоков. Время работы

19.02.2019, 14:32. Показов 5499. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!

Написал программу, которая должна распараллеливать умножение матриц

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
A=\{a_{ik}\} \in M(m\times n), B= \{b_{kj}\} \in M(n \times l)<br />

(код программы ниже).

Распараллеливал по i формулу:

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
c_{ij} = \sum_{k=1}^n a_{ik}b_{kj}, \quad i = 1,2, \ldots m, \quad j = 1,2,\ldots,l.<br />

Тестировал на матрицах размера 2000 x 2000, 2000 x 2000 на машине с 4-мя процессорами.
Запускал с 2, 3, 4 потоками.

Вопрос: Почему программа работает медленнее, чем последовательный вариант?
Причем чем больше потоков, тем медленнее.


Использовать одну память для чтения несколькими потоками нельзя?


C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<time.h>
 
 
 
typedef struct Thread_Data {
    pthread_t id; 
    double ** a;
    double ** b;
    double ** c;
    int from; 
    int to;
    int col2; 
    int row2;
} Thread_Data;
void * Thread_Function(void * arg) {
    int i, j, k;
    Thread_Data * data = (Thread_Data *) arg;
    for(i = data -> from; i < data -> to; i++) {
        for(j = 0; j < data -> col2; j++) {
            data -> c[i][j] = 0.0;
            for(k = 0; k < data -> row2; k++)
                data -> c[i][j] += data -> a[i][k] * data -> b[k][j];
        }
    }
    return NULL;
}
void mult_mat (int thread_count, double ** mat1, double ** mat2, double ** res, int r1, int r2, int c2) {
    int s  = r1 / thread_count;
    int i;
    Thread_Data * data;
    data = (Thread_Data *) malloc(thread_count * sizeof(Thread_Data));
    for(i = 0; i < thread_count - 1; i++) {
        data[i].a = mat1;
        data[i].b = mat2;
        data[i].c = res;
        data[i].from = i * s;
        data[i].to = (i + 1) * s;
        data[i].col2 = c2;
        data[i].row2 = r2;
        pthread_create(&(data[i].id), NULL, Thread_Function, &(data[i]));
    }
    data[thread_count - 1].a = mat1;
    data[thread_count - 1].b = mat2;
    data[thread_count - 1].c = res;
    data[thread_count - 1].from = (thread_count - 1) * s;
    data[thread_count - 1].to = r1;
    data[thread_count - 1].col2 =c2;
    data[thread_count - 1].row2 = r2;
 
    pthread_create(&(data[thread_count - 1].id), NULL, Thread_Function, &(data[thread_count - 1]));
 
    for( i = 0; i < thread_count; i++)
        pthread_join(data[i].id, NULL);
}
int main(int argc, char* argv[]) {
    double **a, **b, **c;
    int m, n, k, i, j, nproc;
    unsigned start_time, end_time, time;
    FILE *fin, *fout;
    fin = fopen("input.txt", "r");
    fscanf(fin, "%d %d%d", &m, &n, &k);
    a  = (double **)malloc(m * sizeof(double *));
    for(i = 0; i < m; i++)
        a[i] = (double *) malloc(n * sizeof(double));
    b  = (double **)malloc(n * sizeof(double *));
    for(i = 0; i < n; i++)
        b[i] = (double *) malloc(k * sizeof(double));
    c  = (double **)malloc(m * sizeof(double *));
    for(i = 0; i < m; i++)
        c[i] = (double *) malloc(k * sizeof(double));
    printf("Ok \n");
    for(i= 0; i< m; i++) {
        for(j = 0; j < n; j++)
            fscanf(fin, "%lf", &a[i][j]);
    }
    for(i= 0; i< n; i++) {
        for(j = 0; j < k; j++)
            fscanf(fin, "%lf", &b[i][j]);
    }
    start_time = clock();
    nproc = atoi(argv[1]);
    mult_mat(nproc, a, b, c, m, n, k);
    fout = fopen("output.txt", "w");
    for(i = 0; i < m; i++) {
        for(j = 0; j < k; j++)
            fprintf(fout, "%lf ", c[i][j]);
        fprintf(fout, "\n");
    }
    end_time = clock();
    printf("time = %lf \n", (end_time - start_time) * 1.0 / CLOCKS_PER_SEC);
    return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.02.2019, 14:32
Ответы с готовыми решениями:

Сложить матрицы с помощью потоков и узнать время работы
Добрый вечер дорогие форумчане. Такая задача: сложить матрицы с помощью потоков и узнать время работы. Я могу это сделать через Thread в...

Распараллеливание потоков для нахождения суммы матрицы <omp.h>
Доброго дня. Сегодня слушал занимательную лекцию об распараллеливание потоков и получил задание: есть матрица 10,10 инициализированная...

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

23
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
20.02.2019, 08:32
Цитата Сообщение от prime2019 Посмотреть сообщение
Вопрос: Почему программа работает медленнее, чем последовательный вариант?
Причем чем больше потоков, тем медленнее.
Вы выбрали не ту ф-цию для подсчета времени. clock() = процессорное время программы. Пусть в один поток задача работает 100 условных единиц времени. Разбив ее на N частей, мы получим те же 100 единиц процессорного времени N * ( 100 / N) + не нулевые накладные расходы на поддержку нитей.
Возьмите например clock_gettime(CLOCK_MONOTONIC, )
2
0 / 0 / 0
Регистрация: 19.02.2019
Сообщений: 5
20.02.2019, 12:50  [ТС]
Цитата Сообщение от prik Посмотреть сообщение
Вы выбрали не ту ф-цию для подсчета времени. clock() = процессорное время программы. Пусть в один поток задача работает 100 условных единиц времени. Разбив ее на N частей, мы получим те же 100 единиц процессорного времени N * ( 100 / N) + не нулевые накладные расходы на поддержку нитей.
Возьмите например clock_gettime(CLOCK_MONOTONIC, )
Спасибо за ответ! Обязательно рассмотрю указанную функцию.

Возникает несколько вопросов. Прошу прощения, если скажу глупость.

Суть распараллеливания - это ведь ускорение
времени выполнения программы.
В моем понимании функция clock() отражает время выполнения основной части программы.
Разве это не так?

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

Неужели на таком примере (умножение матриц) нельзя
увидеть эффект распараллеливания? (ускорение времени)

Или нужны входные данные побольше (матрицы) и побольше количество процессоров?
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
20.02.2019, 13:54
Цитата Сообщение от prime2019 Посмотреть сообщение
Суть распараллеливания - это ведь ускорение
времени выполнения программы.
В данном случае, да.
Цитата Сообщение от prime2019 Посмотреть сообщение
моем понимании функция clock() отражает время выполнения основной части программы.
Нет. Я наверное плохо написал... Это число тиков ОС в течении которых ваша программа, включая _все_ ее нити кушала процессор. Если в один поток задача была решена за 100 тиков, то разбив ее на 4 подзадачи путем ограничения объема обрабатываемых каждой частью данных мы получим 25*4 = те же 100 тиков. Т.е. замеряется совсем не та величина.
Цитата Сообщение от prime2019 Посмотреть сообщение
В моем примере даже визуально выполнение параллельной программы
проходит дольше чем последовательной (если смотреть за терминалом после запуска программы).
Если ядра настоящие, то странно. Предлагаю все-таки промерять время Ответы у одно/много поточных решений совпадают?
Цитата Сообщение от prime2019 Посмотреть сообщение
Или нужны входные данные побольше (матрицы) и побольше количество процессоров?
Нет.
1
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
20.02.2019, 23:34
Цитата Сообщение от prime2019 Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void mult_mat (int thread_count, ...) {
/*****/
  Thread_Data * data;
  data = (Thread_Data *) malloc(thread_count * sizeof(Thread_Data));
  for(i = 0; i < thread_count - 1; i++) {
     /********/
     pthread_create(&(data[i].id), NULL, Thread_Function, &(data[i]));
  }
  /*******/
 
  pthread_create(&(data[thread_count - 1].id), NULL, Thread_Function, &(data[thread_count - 1]));
 
  for( i = 0; i < thread_count; i++)
      pthread_join(data[i].id, NULL);
}
В цикле насоздавали потоков. Затем ещё один без цикла. И после этого в следующем цикле начинаем ждать завершения потока[i], но man pthread_join() нам говорит: "Функция pthread_join() блокирует вызывающий поток, пока указанный поток не завершится."
Может в этом причина?
Попробуй pthread_tryjoin_np() или синхронизироваться через семафоры...

З.Ы. но мне кажется - дело в "лёгкости" задачи для потока. Сколько там получается - 4 млн умножений и при этом данные, наполовину в кеше 3лвл? Кроме того как компиируешь? попробуй указать gcc -O0 (отрубить все оптимизации)

З.З.Ы Как получить доступ к input.txt? - могу поэкспериментировать...
1
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 08:08
Цитата Сообщение от drfaust Посмотреть сообщение
Может в этом причина?
Попробуй pthread_tryjoin_np() или синхронизироваться через семафоры...
Ересь какая-то
Цитата Сообщение от drfaust Посмотреть сообщение
Сколько там получается - 4 млн умножений
Чуть больше 8000 млн.
Цитата Сообщение от drfaust Посмотреть сообщение
могу поэкспериментировать...
Можете просто выкинуть чтение из файла, пусть мусор перемножает. m=n=k=2000
0
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
21.02.2019, 08:33
Цитата Сообщение от prik Посмотреть сообщение
Можете просто выкинуть чтение из файла, пусть мусор перемножает.
Чтение из файла не считается clock`ом. Хотя первый запуск, пока файло ещё не в кеше будет "визуально тормозить".
Цитата Сообщение от prik Посмотреть сообщение
Ересь какая-то
Цитата Сообщение от drfaust Посмотреть сообщение
Может в этом причина?
В качестве эксперимента...

Вообще хотелось бы проверить у себя утверждение
Цитата Сообщение от prime2019 Посмотреть сообщение
Почему программа работает медленнее, чем последовательный вариант?
но лень ваять входной файлик/заполнять "рандомом". Лучше конечно проверять именно на его файлике и исходной_проге, не вмешиваясь.
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 08:56
Цитата Сообщение от drfaust Посмотреть сообщение
Чтение из файла не считается clock`ом. Хотя первый запуск, пока файло ещё не в кеше будет "визуально тормозить".
На фоне времени вычислений эта задержка стремиться к нулю.
Цитата Сообщение от drfaust Посмотреть сообщение
В качестве эксперимента...
Просто, не понимаю чем спячка в pthread_join() может быть хуже ожидания на любом другом объекте синхронизации...
Цитата Сообщение от drfaust Посмотреть сообщение
но лень ваять входной файлик/заполнять "рандомом
Я потому и предложил вам, как готовому ставить эксперименты, выкинуть чтение полностью, заменив его на
C
1
m = n = k = 2000;
0
0 / 0 / 0
Регистрация: 19.02.2019
Сообщений: 5
21.02.2019, 10:04  [ТС]
Цитата Сообщение от prik Посмотреть сообщение
Если ядра настоящие, то странно. Предлагаю все-таки промерять время Ответы у одно/много поточных решений совпадают?Нет.
Вчера не было возможности написать.

Ответы у одно/много поточных решений совпадают.

По поводу ядер.
Я тестировал на двух машинах.

Одна может быть не в счет.
Там тестировал на гостевой Ubuntu в VirtualBox.
Для гостевой Ubuntu выделено 2 ядра из 4.
Хостовая Win10.


На второй машине стоят две системы (параллельно): Ubuntu и Win7.

Процессор там Intel(R) Core(TM) i3-2120 CPU @ 3.30 GHz
c 4-мя ядрами.

В терминале в Ubuntu ответ на команду nproc выдет 4.

Вот на второй машине запускал с 2,3,4 потоками.
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 10:33
Лучший ответ Сообщение было отмечено prime2019 как решение

Решение

Цитата Сообщение от prime2019 Посмотреть сообщение
Процессор там Intel(R) Core(TM) i3-2120 CPU @ 3.30 GHz
c 4-мя ядрами.
Тут 2 ядра, HT можно не считать. Но все равно, разница во времени должна быть.
таки поменяйте ваш xxx_time = clock(); на
C
1
2
3
4
5
6
7
8
9
10
11
12
struct timespec start_time, end_time, time;
 
clock_gettime(CLOCK_MONOTONIC, &start_time);
...
clock_gettime(CLOCK_MONOTONIC, &end_time);
time.tv_sec = end_time.tv_sec - start_time.tv_sec;
time.tv_nsec = end_time.tv_nsec - start_time.tv_nsec;
if (time.tv_nsec < 0) {
  time.tv_sec--;
  time.tv_nsec += 1000000000L;
}
printf("time = %lld.%ld \n", time.tv_sec, time.tv_nsec);
и приходите с результатами.
1
0 / 0 / 0
Регистрация: 19.02.2019
Сообщений: 5
21.02.2019, 12:17  [ТС]
Цитата Сообщение от drfaust Посмотреть сообщение
В цикле насоздавали потоков. Затем ещё один без цикла. И после этого в следующем цикле начинаем ждать завершения потока[i], но man pthread_join() нам говорит: "Функция pthread_join() блокирует вызывающий поток, пока указанный поток не завершится."
Может в этом причина?
Попробуй pthread_tryjoin_np() или синхронизироваться через семафоры...
Функция pthread_join() ведь нужна для того чтобы главный поток
дождался созданные им остальные потоки.

Во многих примерах (в частности, в примерах книги Богачева К.Ю. "Основы параллельного программирования")
есть вызов функции pthread_join().

Цитата Сообщение от drfaust Посмотреть сообщение
З.Ы. но мне кажется - дело в "лёгкости" задачи для потока. Сколько там получается - 4 млн умножений и при этом данные, наполовину в кеше 3лвл? Кроме того как компиируешь? попробуй указать gcc -O0 (отрубить все оптимизации)
Я компилирую gcc -o main -pthread mult_matrix.c.
Попробовал с ключом -o0, компилятор ругается, причем я таких слов не знаю.

Цитата Сообщение от drfaust Посмотреть сообщение
З.З.Ы Как получить доступ к input.txt? - могу поэкспериментировать...
Файл весит 72 Mb. Не загружается.
Заполнял рандомно.
Вот код программы, которая заполняла файл.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
 
int main() {
    
    FILE * fp;
    int m, n, k;
    int i, j;
    double tmp;
    srand(time(NULL));
    fp = fopen("input.txt", "w");
    if(!fp)
        printf("Couldn't open the file \n");
    scanf("%d %d %d", &m, &n, &k);
    fprintf(fp, "%d %d %d \n", m, n, k);
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            tmp = (rand() % 20) / 10000.0 ;
            fprintf(fp, "%lf ", tmp);
        }
        fprintf(fp, "\n");
    }
    for(i = 0; i < n; i++) {
        for(j = 0; j < k; j++) {
            tmp = (rand() % 20) / 10000.0 ;
            fprintf(fp, "%lf ", tmp);
        }
        fprintf(fp, "\n");
    }
    fclose(fp);
    return 0;
}
Добавлено через 1 час 19 минут
Цитата Сообщение от prik Посмотреть сообщение
Тут 2 ядра, HT можно не считать. Но все равно, разница во времени должна быть.
таки поменяйте ваш xxx_time = clock(); на
C
1
2
3
4
5
6
7
8
9
10
11
12
struct timespec start_time, end_time, time;
 
clock_gettime(CLOCK_MONOTONIC, &start_time);
...
clock_gettime(CLOCK_MONOTONIC, &end_time);
time.tv_sec = end_time.tv_sec - start_time.tv_sec;
time.tv_nsec = end_time.tv_nsec - start_time.tv_nsec;
if (time.tv_nsec < 0) {
  time.tv_sec--;
  time.tv_nsec += 1000000000L;
}
printf("time = %lld.%ld \n", time.tv_sec, time.tv_nsec);
и приходите с результатами.
Спасибо большое! Работает!

Запускал три раза оба варианта программы с Вашим кодом.

Время работы последовательной программы:

1) 94.127962015

2) 94.233204728

3) 94.10741871


Время работы параллельной программы:

1) 49.317953911

2) 49.14839388

3) 49.404053058

Параллельную программу запускал на двух потоках.

Буду разбираться с функциями clock() и clock_gettime() и распараллеливанием в целом.

Да, кстати что такое НТ из вашего сообщения?
Цитата Сообщение от prik Посмотреть сообщение
Тут 2 ядра, HT можно не считать.
Напоследок пара вопросов по обучению распараллеливанию потоками:

1) Что читать? Что слушать, смотреть?

2) Какие задачи полезны для освоения распараллеливания?
0
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
21.02.2019, 12:46
Цитата Сообщение от prime2019 Посмотреть сообщение
-o0
-O0 это O английское большое, затем ноль. По дефолту gcc компилит с -O2.

Цитата Сообщение от prime2019 Посмотреть сообщение
Заполнял рандомно.
Вот код программы, которая заполняла файл.
Будет время поэкспериментирую...

Цитата Сообщение от prime2019 Посмотреть сообщение
Да, кстати что такое НТ из вашего сообщения?
Технология HyperThreading от Intel`а. Позволяет на одном ядре выполнять "параллельно" два потока, т.к. есть несколько конвейеров(u и v, если не изменяет склероз) внутри ядра. Даёт прирост до 30%
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 13:04
Лучший ответ Сообщение было отмечено prime2019 как решение

Решение

Цитата Сообщение от drfaust Посмотреть сообщение
По дефолту gcc компилит с -O2.
Я бы наоборот с -O3 собрал, думаю %40-%50 для этого кода даст.
Цитата Сообщение от prime2019 Посмотреть сообщение
Да, кстати что такое НТ из вашего сообщения?
Выше уже ответили. Можно добавить, что на некоторых задачах вместо роста можно получить и тормоза.
Цитата Сообщение от prime2019 Посмотреть сообщение
Напоследок пара вопросов по обучению распараллеливанию потоками:
Книжек не знаю. По моему достаточно посмотреть на pthread.h и никогда, не при каких обстоятельствах не строить предположений о порядке выполнения параллельного кода.
0
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
21.02.2019, 19:16
Лучший ответ Сообщение было отмечено prime2019 как решение

Решение

Цитата Сообщение от prik Посмотреть сообщение
и никогда, не при каких обстоятельствах не строить предположений о порядке выполнения параллельного кода.
А так же всегда думать о том, что несколько потоков могут лезть к одним и тем же данным, если чтение - ладно, а если кто-то ещё и писать будет, то всё... без синхронизации получится бред.

Добавлено через 5 часов 48 минут
Цитата Сообщение от prik Посмотреть сообщение
Вы выбрали не ту ф-цию для подсчета времени. clock() = процессорное время программы. Пусть в один поток задача работает 100 условных единиц времени. Разбив ее на N частей, мы получим те же 100 единиц процессорного времени
Да, прогнав прогу через time я сразу обратил внимание на некоторые цифры. А когда залез в "man 3 clock" и на opennet, то увидел подтверждение своим подозрениям:

man 3 орёт "Функция clock() возвращает приблизительное процессорное время, использованное программой." (archlinux почти ежедневнообновляемый) - совсем не очевидно, что считается суммарное процессорное время.

opennet намного короче, но сразу даёт понять о чём идёт речь: "Функция clock() возвращает суммарное процессорное время, использованное программой. " тут уже всё понятно...
Мои результат с использованием clock():
Bash
1
2
3
4
5
6
7
8
9
10
11
12
faust@archlinux par]$ time -p ./a.out 4
Ok 
time = 181.489280 
real 49,05
user 183,29
sys 0,15
[faust@archlinux par]$ time -p ./a.out 1
Ok 
time = 181.134845 
real 183,93
user 183,01
sys 0,12
Добавлено через 8 минут
Выше я компилил с -O0 , сейчас решил посмотреть что будет с 03:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
[faust@archlinux par]$ gcc -O3 par.c -lpthread
[faust@archlinux par]$ time -p ./a.out 4                                                                                
Ok                                                                                                                                     
time = 106.692476 
real 30,38
user 108,50
sys 0,18
[faust@archlinux par]$ time -p ./a.out 1
Ok 
time = 106.369144 
real 109,38
user 108,07
sys 0,23
Впечатляет, от 60% до 80% скорости

Добавлено через 10 минут
Интересно, оказывается и -Og работает, я думал это аналог -O0 - ан-нет:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
faust@archlinux par]$ gcc -Og par.c -lpthread
[faust@archlinux par]$ time -p ./a.out 1
Ok 
time = 144.695144 
real 147,47
user 146,53
sys 0,17
[faust@archlinux par]$ time -p ./a.out 4
Ok 
time = 142.832517 
real 40,87
user 144,55
sys 0,25
[faust@archlinux par]$
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 19:30
Цитата Сообщение от drfaust Посмотреть сообщение
Впечатляет, от 60% до 80% скорости
На -O2 циклы не раскрываются. А тут все нагрузка в
C
1
2
3
4
5
6
7
    for(i = data -> from; i < data -> to; i++) {
        for(j = 0; j < data -> col2; j++) {
            data -> c[i][j] = 0.0;
            for(k = 0; k < data -> row2; k++)
                data -> c[i][j] += data -> a[i][k] * data -> b[k][j];
        }
    }
1
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
21.02.2019, 19:37
Мне больше непонятно с -Og "включает все оптимизации, которые не мешают отладке".
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 19:45
drfaust, -Og это O[1] без
Цитата Сообщение от drfaust Посмотреть сообщение
которые не мешают отладке".
0
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
21.02.2019, 20:00
Цитата Сообщение от prik Посмотреть сообщение
Og это O[1] без
Теперь понятно - просто альяс...

Вот сделал по рекомендации prik, через clock_gettime() - теперь можно отказаться от time и видеть действительное время работы:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[faust@archlinux par]$ gcc -O3 par.c -lpthread
[faust@archlinux par]$ time -p ./a.out 1
Ok 
time = 105.250617792 
real 109,28
user 108,25
sys 0,18
[faust@archlinux par]$ time -p ./a.out 4
Ok 
time = 26.697527828 
real 30,50
user 109,54
sys 0,18
[faust@archlinux par]$ gcc -O0 par.c -lpthread
[faust@archlinux par]$ time -p ./a.out 1
Ok 
time = 181.4380876 
real 184,96
user 183,93
sys 0,13
time учитывает ещё и файловый ввод/вывод. Заметил, что у ТС отсчёт времени (через clock) после выполнения происходит после выхлопа в файл, что нарушает точность измерений - исправил.

Сейчас погоняю на разном кол-ве потоков и посмотрю что будет. Оптимизации только -O3, исходный текст с clock_gettime в качестве образца, переделывать не буду(хотя там, если полопатить....)
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
21.02.2019, 20:38
Цитата Сообщение от drfaust Посмотреть сообщение
Сейчас погоняю на разном кол-ве потоков и посмотрю что будет
Если не лень:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int main(int argc, char* argv[]) {
    double **a, **b, **c;
    int m, n, k, i, j, nproc, x;
    struct timespec start_time, end_time, time;
    FILE *fin;
 
    if (argc != 2)
        return 1;
    fin = fopen("input.txt", "r");
    fscanf(fin, "%d %d%d", &m, &n, &k);
    a  = (double **)malloc(m * sizeof(double *));
    for(i = 0; i < m; i++)
        a[i] = (double *) malloc(n * sizeof(double));
    b  = (double **)malloc(n * sizeof(double *));
    for(i = 0; i < n; i++)
        b[i] = (double *) malloc(k * sizeof(double));
    c  = (double **)malloc(m * sizeof(double *));
    for(i = 0; i < m; i++)
        c[i] = (double *) malloc(k * sizeof(double));
    //printf("Ok \n");
    for(i= 0; i< m; i++) {
        for(j = 0; j < n; j++)
            fscanf(fin, "%lf", &a[i][j]);
    }
    for(i= 0; i< n; i++) {
        for(j = 0; j < k; j++)
            fscanf(fin, "%lf", &b[i][j]);
    }
    nproc = atoi(argv[1]);
    for (x = nproc; x > 0; x--) {
        clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
        mult_mat(x, a, b, c, m, n, k);
        clock_gettime(CLOCK_MONOTONIC_RAW, &end_time);
        timespecsub(&end_time, &start_time, &time);
        printf("%dx%d * %dx%d, %d threads: %lld.%ld \n", m, n, n, k, x, time.tv_sec, time.tv_nsec);
    }
    return 0;
}
Прогоняет тест в цикле с числом потоков от argv[1] до 1, не создает output.txt, если запущен ntpd - не влияет на время (линуксизм)
0
599 / 421 / 136
Регистрация: 02.10.2008
Сообщений: 1,796
Записей в блоге: 1
21.02.2019, 21:08
Ну вот, то чего и ожидал ТС. У меня 4 ядерный феном (никаких HT), на 5 потоках - я полазил в гуглохроме, и потому сбил показания... Оверхед от операционки(еа переключение процессов) в данном случае минимален:
Кликните здесь для просмотра всего текста
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
[faust@archlinux par]$ ./a.out 1 && ./a.out 1 && ./a.out 1
Ok 
time = 179.884671625 
Ok 
time = 180.211107125 
Ok 
time = 180.478086379 
[faust@archlinux par]$ ./a.out 2 && ./a.out 2 && ./a.out 2
Ok 
time = 90.122336334 
Ok 
time = 90.107070148 
Ok 
time = 90.37819941 
[faust@archlinux par]$ ./a.out 3 && ./a.out 3 && ./a.out 3
Ok 
time = 60.282967531 
Ok 
time = 60.283562032 
Ok 
time = 60.307121332 
[faust@archlinux par]$ ./a.out 4 && ./a.out 4 && ./a.out 4
Ok 
time = 45.513118739 
Ok 
time = 45.337107981 
Ok 
time = 45.127946900 
[faust@archlinux par]$ ./a.out 5 && ./a.out 5 && ./a.out 5
Ok 
time = 46.966589466 
Ok 
time = 45.937451430 
Ok 
time = 46.721443653 
[faust@archlinux par]$ ./a.out 6 && ./a.out 6 && ./a.out 6
Ok 
time = 48.661131606 
Ok 
time = 49.571588977 
Ok 
time = 48.592256834 
[faust@archlinux par]$ ./a.out 7 && ./a.out 8 && ./a.out 9
Ok 
time = 44.885776785 
Ok 
time = 39.259477979 
Ok 
time = 44.622543398 
[faust@archlinux par]$ ./a.out 10 && ./a.out 10 && ./a.out 10
Ok 
time = 45.644115020 
Ok 
time = 45.962891134 
Ok 
time = 45.543576141 
[faust@archlinux par]$


Добавлено через 27 минут
Предупреждение: неявная декларация функции «timespecsub»;
В каком стандарте/версии gcc собираешь? Откуда этот макрос взялся?
#include <sys/time.h>
(See libbsd(7) for include usage.)
Откуда он взялся?

Добавлено через 55 секунд
Bash
1
2
3
[faust@archlinux par]$ gcc -O3 par1.c -lpthread -lbsd -o 1
par1.c: В функции «main»:
par1.c:93:9: предупреждение: неявная декларация функции «timespecsub»;
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.02.2019, 21:08
Помогаю со студенческими работами здесь

Замедление работы потоков если запущено несколько потоков
Есть отдельный поток который движет красным квадратом. Он каждую миллисекунду меняет положение квадрата на пиксель. Есть другой поток, он...

Распараллеливание работы между ядрами.
Кто знает подскажите пожалуйсто. Есть программа на java, с использованием потоков. И есть компьютер 2-х, 4-х ядерный. Меня интересует...

Разделить время выполнения потоков
Я только начал изучать потоки, так что возможно это нубский вопрос, но как организовать чтобы если работает только один поток, то весь...

Посчитать время события - время работы кассиров (система массового обслуживания)
Есть программа, моделирующая следующую задачу (система массового обслуживания): В бухгалтерии предприятия имеются два кассира, каждый...

Выводить текущее время в определенные позиции консоли во время работы
Портирую консольное приложение. Есть код, который работал после компиляции в BC++ 3.1, после компиляции под MinGW GCC программа не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru