Потоки с общими переменными

Я пытался использовать несколько потоков, чтобы вставить в boost::bimap, У меня есть некоторая общая переменная между потоками, которую мне нужно передать по ссылке, и некоторые из них изменяются при каждом выполнении потока. Однако я получаю ошибку:

Ошибка сегментации (ядро сброшено)

У меня есть следующий код со мной. Я пытался избежать одновременного доступа к переменным с помощью std::lock_guard<std::mutex> lock(mtx), но не в состоянии заставить его работать.

parallel_index.cpp

#include <iostream>
#include <string>
#include <algorithm>
#include <thread>
#include <mutex>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>
#include "parallel_index.h"

namespace bimaps = boost::bimaps;
typedef boost::bimap<bimaps::unordered_set_of<uint64_t>,
bimaps::unordered_multiset_of<std::string> > bimap_reference;
typedef bimap_reference::value_type position;
bimap_reference reference_index_vector;size_t total_threads = std::thread::hardware_concurrency();

std::string sequence_content = "ABCDDBACDDDCBBAAACBDAADCBDAAADCBDADADACBDDCBBBCDCBCDAADCBBCDAAADCBDA";
uint64_t sequence_length = sequence_content.length();
int split = 5;
uint64_t erase_length = 0;
unsigned int seq_itr = 0;

std::mutex mtx;   // to protect against concurent access
int main(){
thread_test::create_index index;
std::thread threads[total_threads];
std::cout << total_threads <<  " threads lanched" << std::endl;
for(unsigned int i = 0; i < total_threads; i++){
threads[i] = std::thread(&thread_test::create_index::reference_index_hash, index,
std::ref(sequence_length), std::ref(split), std::ref(sequence_content), std::ref(erase_length));
}

for(unsigned int i = 0; i < total_threads; i++){
threads[i].join();
}
}/*
* Creating index
*/
void thread_test::create_index::reference_index_hash(uint64_t &sequence_length, int &split,
std::string &sequence_content, uint64_t &erase_length  ){

for (; seq_itr < sequence_length; ++seq_itr ){

std::lock_guard<std::mutex> lock(mtx);
std::string splitstr = sequence_content.substr(erase_length, split);
reference_index_vector.insert(position(seq_itr, splitstr));
seq_itr += split-1;
erase_length += split;

if(erase_length > 10000){
sequence_content.erase(0,erase_length);
erase_length = 0;
}
}for( bimap_reference::const_iterator iter = reference_index_vector.begin(), iend = reference_index_vector.end();
iter != iend; ++iter ) {
std::cout << iter->left << " <--> "<< iter->right <<std::endl;
}}

parallel_index.h

#ifndef PARALLEL_INDEX_H_
#define PARALLEL_INDEX_H_#include<iostream>
#include <algorithm>
#include <utility>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>//typedef boost::unordered_map<int, std::pair<int, unsigned long int>& > reference_map;

namespace bimaps = boost::bimaps;

typedef boost::bimap<bimaps::unordered_set_of<uint64_t>,
bimaps::unordered_multiset_of<std::string > > bimap_reference;
typedef bimap_reference::value_type position;
extern bimap_reference reference_index_vector;namespace thread_test{

class create_index{
public:
void reference_index_hash(uint64_t &sequence_length, int &split,
std::string &sequence_content, uint64_t &erase_length);
};
}#endif /* PARALLEL_INDEX_H_ */

——————————-РЕДАКТИРОВАТЬ———————————

Я попытался разделить содержимое строки на разделы, равные количеству потоков, чтобы каждый поток имел свою локально доступную часть. Но ничего не работает. Иногда он заканчивает первый поток и останавливается после Segmentation fault (core dumped),

parallel_index.cpp

#include <iostream>
#include <string>
#include <algorithm>
#include <thread>
#include <mutex>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>
#include "parallel_index.h"

namespace bimaps = boost::bimaps;
typedef boost::bimap<bimaps::unordered_set_of<uint64_t>,
bimaps::unordered_multiset_of<std::string> > bimap_reference;
typedef bimap_reference::value_type position;
bimap_reference reference_index_vector;//create threads
size_t total_threads = std::thread::hardware_concurrency();std::string sequence_content = "ABCDDBACDDDCBBAAACBDAADCBDAAADCBDADADACBDDCBBBCDCBCDAADCBBCDAAADCBDADDCCCAAABBBAAACDCA";
uint64_t sequence_length = sequence_content.length();
int split = 5;

// split the sequence_content equal to the number of threads, and assign each partition to each thread.
uint64_t each_partition_len = sequence_content.length()/total_threads- (sequence_content.length()/total_threads)%split ;
uint64_t last_partition_len = sequence_content.length()/total_threads +
(((sequence_content.length()/total_threads)%split)*(total_threads-1)) + sequence_content.length()%total_threads;std::mutex mtx;   // to protect against concurent access
int main(){
thread_test::create_index index;
std::thread threads[total_threads];

std::cout << total_threads <<  " threads lanched" << std::endl;

for(unsigned int i = 0; i < total_threads; i++){

if(i < total_threads-1)
threads[i] = std::thread(&thread_test::create_index::reference_index_hash, index,
std::ref(each_partition_len), std::ref(split), std::ref(sequence_content), i);

else
threads[i] = std::thread(&thread_test::create_index::reference_index_hash, index,
std::ref(last_partition_len), std::ref(split), std::ref(sequence_content), i);

//std::lock_guard<std::mutex> lck(mtx);
std::cout << "launched thread " << i << "with id " << threads[i].get_id() << std::endl;
}for( bimap_reference::const_iterator iter = reference_index_vector.begin(), iend = reference_index_vector.end();
iter != iend; ++iter ) {
std::cout << iter->left << " <--> "<< iter->right <<std::endl;
}

for( unsigned int i = 0; i < total_threads; ++i){
if(threads[i].joinable()){
std::cout << "trying to join thread " << i << std:: endl;
threads[i].join();
std::cout << "thread joined " << i << std:: endl;
}
}

for( bimap_reference::const_iterator iter = reference_index_vector.begin(), iend = reference_index_vector.end();
iter != iend; ++iter ) {
std::cout << iter->left << " <--> "<< iter->right <<std::endl;
}
}
/*
* Creating index
*/
void thread_test::create_index::reference_index_hash(uint64_t &sequence_length, int &split,
std::string &sequence_content, int i  ){

uint64_t seq_strt = 0;

//  set seq_strt
if(i == 0)
seq_strt = sequence_length * i;
else
seq_strt = sequence_length * i + 1;

for (uint64_t seq_itr = seq_strt; seq_itr <= sequence_length; ++seq_itr ){std::string splitstr = sequence_content.substr(seq_itr, split);

mtx.lock();
//std::lock_guard<std::mutex> lock(mtx);
reference_index_vector.insert(position(seq_itr, splitstr));
mtx.unlock();

seq_itr += split-1;

}
}

parallel_index.h

#ifndef PARALLEL_INDEX_H_
#define PARALLEL_INDEX_H_#include<iostream>
#include <algorithm>
#include <utility>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>

namespace bimaps = boost::bimaps;

typedef boost::bimap<bimaps::unordered_set_of<uint64_t>,
bimaps::unordered_multiset_of<std::string > > bimap_reference;
typedef bimap_reference::value_type position;
extern bimap_reference reference_index_vector;namespace thread_test{

class create_index{
public:
void reference_index_hash(uint64_t &sequence_length, int &split,
std::string &sequence_content, int i);
};
}#endif /* PARALLEL_INDEX_H_ */

2

Решение

Я чувствую себя виновником segmentation fault ничего кроме static связывание библиотек. Его не увеличивая seq_itr к значению, превышающему фактическую длину последовательности, потому что ваш цикл for никогда не позволит ввести, если seq_itr больше, чем фактическая длина последовательности. Вы пытаетесь, удалив -static флаг, и он должен работать, не давая ошибки сегментации, однако это не гарантирует правильность другого кода. Подробнее об ошибке сегментации с thread может быть найден Вот

1

Другие решения

Все потоки попытаются получить блокировку в критической секции, чтобы сохранить нетронутым растровое изображение, вам нужна условная переменная, чтобы потоки выполнялись по порядку. Это оправдано, поскольку вы используете seq_itr как локальную переменную внутри reference_index_hash (), и его нужно увеличивать в правильной последовательности.

0

Одна проблема в вашем исходном коде заключается в том, что unsigned int seq_itr Доступ без синхронизации из нескольких потоков. Помимо получения неверных результатов это может привести к seq_itr увеличивается до значения, превышающего фактическую длину последовательности, и следующие обращения могут привести к сбою.

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

Однако во втором примере кода есть проблема с печатью карты непосредственно после запуска потоков с

for( bimap_reference::const_iterator iter = reference_index_vector.begin(), iend = reference_index_vector.end();
iter != iend; ++iter ) {
std::cout << iter->left << " <--> "<< iter->right <<std::endl;
}

Это не даст правильных результатов, поскольку к карте одновременно обращаются все рабочие потоки. Доступ после join()это безопасно.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector