#c #multithreading
#c #многопоточность
Вопрос:
Я пытаюсь написать фрагмент кода, который проходит цикл из 8 ^ 12 итераций, и на каждой итерации, когда выполняются некоторые условия, я возвращаю push_back к вектору (у каждого потока есть свой собственный вектор для push_back, который я объединяю после цикла). Но кажется, что мое выполнение занимает больше времени, чем больше потоков активно. Здесь’ функция (метод объекта) передается в каждый поток:
void HamiltonianKH::mapping_kernel(ull_int start, ull_int stop, std::vector<ull_int>* map_threaded, int _id) {
int n = 1;
out << "A new thread joined tha party! from " << start << " to " << stop << endl;
for (ull_int j = start; j < stop; j ) {
int bSz = 0, fSz = 0, N_e = 0;
std::tie(bSz, fSz, N_e) = calculateSpinElements(this->L, j);
if ((bSz fSz == this->Sz) amp;amp; N_e == this->num_of_electrons)
map_threaded->push_back(j);
if (show_system_size_parameters == true amp;amp; (j - start) % ull_int((stop - start) * n / 4) == 0 amp;amp; j > 0) {
out << n << "-th quarter of " << _id << endl;
n ;
}
}
}
, вот функция caulculate_spinelements:
std::tuple<int, int, int> calculateSpinElements(int L, ull_intamp; j) {
int bSz = 0; //bosonic total spin - spin of upper orbital locked to n=1 filling
int fSz = 0; //fermionic total spin
int N_e = 0; // numer of electrons in given state
std::vector<int> temp = int_to_binary(j, L);
for (int k = 0; k < L; k ) {
if (temp[k] < 4) bSz = 1;
else bSz -= 1;
if (temp[k] % 4 == 1) {
fSz = 1;
N_e = 1;
}
else if (temp[k] % 4 == 2) {
fSz -= 1;
N_e = 1;
}
else if (temp[k] % 4 == 3)
N_e = 2;
}
return std::make_tuple(bSz, fSz, N_e);
}
и это разделение на потоки:
void HamiltonianKH::generate_mapping() {
ull_int start = 0, stop = std::pow(8, L);
//mapping_kernel(start, stop, mapping, L, Sz, num_of_electrons);
//Threaded
std::vector<std::vector<ull_int>*> map_threaded(num_of_threads);
std::vector<std::thread> threads;
threads.reserve(num_of_threads);
for (int t = 0; t < num_of_threads; t ) {
start = t * (ull_int)std::pow(8, L) / num_of_threads;
stop = ((t 1) == num_of_threads ? (ull_int)std::pow(8, L) : (ull_int)std::pow(8, L) * (t 1) / num_of_threads);
map_threaded[t] = new std::vector<ull_int>();
threads.emplace_back(amp;HamiltonianKH::mapping_kernel, this, start, stop, map_threaded[t], t);
}
for (autoamp; t : threads) t.join();
for (autoamp; t : threads) t.~thread();
ull_int size = 0;
for (autoamp; t : map_threaded) {
size = t->size();
}
out << "size = " << size << endl;
for (auto amp; t : map_threaded)
mapping->insert(mapping->end(), t->begin(), t->end());
//sort(mapping->begin(), mapping->end());
if (show_system_size_parameters == true) {
out << "Mapping generated with " << mapping->size() << " elements" << endl;
out << "Last element = " << mapping->at(mapping->size() - 1) << endl;
}
//out << mapping[0] << " " << mapping[mapping.size() - 1] << endl;
assert(mapping->size() > 0 amp;amp; "Not possible number of electrons - no. of states < 1");
}
Переменные: mapping, L, num_of_electrons и Sz являются общедоступными полями в объекте. Весь код содержит более 2000 строк, но выполнение после вызова generate_mapping() не имеет отношения к проблеме.
У кого-нибудь из вас, ребята, есть идея, почему этот фрагмент кода выполняется дольше в большем количестве потоков?
Заранее большое вам спасибо.
Комментарии:
1. Выделение памяти синхронизировано, поэтому все это
push_back
стоит вам.2. Вы ни в коем случае не должны явно уничтожать свои потоки. Они будут уничтожены вектором, которому они принадлежат.
3. Да, но однопоточный и многопоточный вызовы push_back одинаковое количество раз, поэтому я не думаю, что push_back так сильно замедляет этот код:
4. один поток: 12 секунд выполнения 8 потоков: 50 секунд выполнения
5. «Да, но однопоточный и многопоточный вызовы push_back одинаковое количество раз, поэтому я не думаю, что push_back так сильно замедляет этот код» — Блокировка мьютекса в кэше уровня 1 отдельного процессора намного быстрее, чем блокировка мьютекса в общем кэше уровня 3.