LINUX.ORG.RU

Почему не уменьшается время в мультипоточной программе?

 


0

1

Вот такая программа:

#include <thread>
#include <vector>
#include <iostream>

using namespace std;

clock_t etime[128];
vector<unsigned> idx[128];

void eval(unsigned n, unsigned m, unsigned i) {
  etime[i] = clock();
  for (unsigned j = i; j < n; j += m) {
    idx[i].push_back(j);
  }
  etime[i] = clock() - etime[i];
}

int main(int argc, char **argv) {
  unsigned M = atoi(argv[1]);

  for (unsigned i = 0; i < M; i += 1) {
    eval(250000, M, i);
  }

  for (unsigned i = 0; i < M; i += 1) {
    cout << "seq " << etime[i] << endl;
  }
  
  vector<thread> threads;
  for (unsigned i = 0; i < M; i += 1) {
    threads.push_back(thread(eval, 250000, M, i));
  }

  for (auto &th : threads) {
    th.join();
  }
  
  for (unsigned i = 0; i < M; i += 1) {
    cout << "par " << etime[i] << endl;
  }
  
  return 0;
}

По идее, чем больше параметр (число потоков), тем меньше должно быть время выполнения одного потока. На практике получаем, что не так:

$ ./test 1`
seq 7737
par 8529

$ ./test 4
seq 2756
seq 2615
seq 1810
seq 1675
par 12601
par 18108
par 18546
par 15692

Что может быть не так? Может, тут неприменим clock?

★★★

Последнее исправление: eugine_kosenko (всего исправлений: 2)
Ответ на: комментарий от WitcherGeralt

Упс. Забыл зачистить. Ладно, если вот так:

clock_t etime[128];

void eval(unsigned n, unsigned m, unsigned i) {
  vector<unsigned> idx;

  etime[i] = clock();
  for (unsigned j = i; j < n; j += m) {
    idx.push_back(j);
  }
  etime[i] = clock() - etime[i];
}

Даже в таком виде качественной разницы нет:

$ ./test 1
seq 7995
par 9597

$ ./test 4
seq 1992
seq 1892
seq 1853
seq 1869
par 12072
par 6627
par 12020
par 6455
eugine_kosenko ★★★
() автор топика
Последнее исправление: eugine_kosenko (всего исправлений: 1)

Во-первых, твоя задача для треда слишком легкая, основное время приходится на запуск и остановку потоков. Во-вторых, clock() измеряет процессорное время потраченное всей программой, а не одним потоком. Чем больше ядер процессора нагрузишь, тем быстрее результат clock() будет расти.

anonymous
()
Ответ на: комментарий от eugine_kosenko

Сразу после аллокации вектора:

  vector<unsigned> idx;
  idx.reserve(260000);
Dendy ★★★★★
()
Последнее исправление: Dendy (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

По ‘во-вторых’ я что-то такое начал подозревать. То есть, правильно для такого замера пользоваться не clock(), а чем-то вроде time()? Но я смотрю, time, похоже, в секундах меряет, это слишком крупная единица. Есть какие-то варианты time в мили/микросекундах?

eugine_kosenko ★★★
() автор топика
Ответ на: комментарий от eugine_kosenko

конкретно время работы функции меряют клоком. она учитывает только клоки твоего процесса. а time - это обычное время. ось берет прерывания от внутренних часов и считаето свои секунды/наносекунды.

alysnix ★★★
()
Ответ на: комментарий от eugine_kosenko
#include <thread>
#include <vector>
#include <iostream>

using namespace std;

void eval(unsigned n, unsigned m, unsigned i) {
  vector<unsigned> idx;

  for (unsigned j = i; j < n; j += m) {
    idx.push_back(j);
  }
}

int main(int argc, char **argv) {
  unsigned M = atoi(argv[1]);

  auto t = -clock();

  for (unsigned i = 0; i < M; i += 1) {
    eval(250000, M, i);
  }

  cout << "seq " << (t+clock()) << endl;

  t = -clock();

  vector<thread> threads;
  for (unsigned i = 0; i < M; i += 1) {
    threads.push_back(thread(eval, 250000, M, i));
  }

  for (auto &th : threads) {
    th.join();
  }
  
  cout << "par " << (t+clock()) << endl;

  return 0;
}

Вообще, операции по памяти параллелить не так много смысла.

WitcherGeralt ★★
()

По идее, чем больше параметр (число потоков), тем меньше должно быть время выполнения одного потока
Может, тут неприменим clock?

man превышение лимита man тайминг по clock в мультитреде man выхлоп гцц или что у тебя там man погрешность измерений

DllMain
()
Ответ на: комментарий от anonymous

А можно какой то пруф про clock, я вот думал, что под x86_64 это обёртка над rdtsc который уникален на ядро без ht не?

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Вопрос снят после прочтения man clock, перепутал с clock_gettime.

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

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)

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

С хера ли? Не курсе, что переключение потока - очень дорогая операция?

crutch_master ★★★★★
()
Ответ на: комментарий от AKonia

лучше заменить на timespec_get() и 1E-9

anonymous
()
Ответ на: комментарий от crutch_master

Ты пьяный?

Я же говорю, сижник нонче совсем слабенький пошел :(

Разорванный Флакон

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.