I have some issues with C++ thread library. I have adapted my old code for optimization of a new problem and suddenly an uncaught exception is thrown (During runtime). Some threads are joined successfully, but there's always at least one throwing an exception. Only thing which I changed in the code, was data representation. They were earlier held in 2D arrays and now I am using 1D vectors. Here is the exact runtime error I receive:
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: thread::join failed: Invalid argument
Below I provide the minimal reproducible example, throwing the exact same exception like in the case of the complete code.
Here is the main function:
#include <iostream>
#include <thread>
#include <vector>
void reforming(const int, const std::vector<int>&, const std::vector<double>&, const std::vector<double>&);
int main() {
int i, k;
int spec_max = 10;
int seg_max = 4;
size_t pop_size = spec_max * seg_max;
std::vector<int> seg(pop_size);
std::vector<double> por(pop_size);
std::vector<double> por_s(pop_size);
for(i = 0; i < pop_size; i++){
if(i % 2 == 0){
seg[i] = 1;
por[i] = 0.5;
por_s[i] = 0.0015;
} else {
seg[i] = 0;
por[i] = 0.7;
por_s[i] = 0.002;
}
}
std::vector<std::thread> Ref(spec_max);
for(k = 0; k < spec_max; k++){
Ref.emplace_back(reforming, k, seg, por, por_s);
}
for(auto &X : Ref){
X.join();
}
return 0;
}
and the "reforming" function:
#include <iostream>
#include <vector>
void reforming(const int m, const std::vector<int>& cat_check, const std::vector<double>& por,
const std::vector<double>& por_s){
std::cout << m << " Hello from the thread\n";
}
I am using the CLion software on MacOS Catalina and currently have no other OS available to test the code.
The following code:
std::vector<std::thread> Ref(spec_max);
for(k = 0; k < spec_max; k++){
Ref.emplace_back(reforming, k, seg, por, por_s);
}
creates 2 * spec_max threads, the first spec_max threads are default-initialized. Trying to join a default-initialized thread throws std::system_error.
A fix:
std::vector<std::thread> Ref;
Ref.reserve(spec_max);
for(k = 0; k < spec_max; k++){
Ref.emplace_back(reforming, k, seg, por, por_s);
}
Related
Why only last threads executes every time? I'm trying to divide grid into N workers, half of grid always not touchable and other part always proceed by 1 last created thread. Should I use an array instead of vector? Locks also do not help to resolve this problem.
#include <iostream>
#include <unistd.h>
#include <vector>
#include <stdio.h>
#include <cstring>
#include <future>
#include <thread>
#include <pthread.h>
#include <mutex>
using namespace std;
std::mutex m;
int main(int argc, char * argv[]) {
int iterations = atoi(argv[1]), workers = atoi(argv[2]), x = atoi(argv[3]), y = atoi(argv[4]);
vector<vector<int> > grid( x , vector<int> (y, 0));
std::vector<thread> threads(workers);
int start, end, lastworker, nwork;
int chunkSize = y/workers;
for(int t = 0; t < workers; t++){
start = t * chunkSize;
end = start + chunkSize;
nwork = t;
lastworker = workers - 1;
if(lastworker == t){
end = y; nwork = workers - 1;
}
threads[nwork] = thread([&start, &end, &x, &grid, &t, &nwork, &threads] {
cout << " ENTER TO THREAD -> " << threads[nwork].get_id() << endl;
for (int i = start; i < end; ++i)
{
for (int j = 0; j < x; ++j)
{
grid[i][j] = t;
}
}
sleep(2);
});
cout << threads[nwork].get_id() << endl;
}
for(auto& th : threads){
th.join();
}
for (int i = 0; i < y; ++i)
{
for (int j = 0; j < x; ++j)
{
cout << grid[i][j];
}
cout << endl;
}
return(0);
}
[&start, &end, &x, &grid, &t, &nwork, &threads]
This line is the root of the problem. You are capturing all the variables by reference, which is not what you want to do.
As a consequence, each thread uses the same variables, which is also not what you want.
You should only capture grid and threads by reference, the other variables should be captured by value ('copied' into the lambda)
[start, end, x, &grid, t, nwork, &threads]
Also, you are accessing grid wrong everywhere: change grid[i][j] to grid[j][i]
thread([&start, &end, &x, &grid, &t, &nwork, &threads] {
=======
The lambda closure that gets executed by every thread captures a reference to nwork.
Which means that as the for loop iterates and starts every thread, each captured thread will always reference the current value of nwork, at the time it does.
As such, the outer loop probably quickly finishes creating each thread object before all the threads actually initialize and actually enter the lambda closure, and each closure sees the same value of nwork, because it is captured by reference, which is the last thread id.
You need to capture nwork by value instead of by reference.
You're passing all the thread parameters are references to the thread lambda. However, when the loop continues in the main thread, the thread parameter variables change, which changes their values in the threads as well, messing up all the previously-created threads.
i'm new in c++ programing and need some help to use a thread library with vector library...
first I follow this tutorial
but the compiler (visual studio 2013) show me errors and I don't know how correct it:
first declaration of function
void Fractal::calcIterThread(vector<vector<iterc>> &matriz, int desdePos, int hastaPos, int idThread){
...
}
in main loop
vector<vector<iterc>> res;
res.resize(altoPantalla);
for (int i = 0; i < altoPantalla; i++){
res[i].resize(anchoPantalla);
}
int numThreads = 10;
vector<thread> workers(numThreads);
for (int i = 0; i < numThreads; i++){ //here diferent try
thread workers[i] (calcIterThread, ref(res), inicio, fin, i)); // error: expresion must have a constant value
workers[i] = thread(calcIterThread, ref(res), inicio, fin, i)); // error: no instance of constructor "std::thread::thread" matches the argument list
}
...rest of code...
thanks for any help to clarify
Try this:
#include <functional>
#include <thread>
#include <vector>
// ...
int numThreads = 10;
std::vector<std::thread> workers;
for (int i = 0; i != numThreads; ++i)
{
workers.emplace_back(calcIterThread, std::ref(res), inicia, fin, i);
}
for (auto & t : workers)
{
t.join();
}
finally I can solve the problem with this change in my code...
workers.emplace_back(thread{ [&]() {
calcIterThread(ref(res), inicio, fin, i);
}});
I'm trying to write my first neural network in C++ and I'm having trouble with it.
Basically I get
segmentation fault 11
So I tried to debug and it turned out that after the line 41 the program stops for a reason called
EXC_BAD_ACCESS,
what does it mean? how can I turn around it? I've seen from other posts that segmentation fault means running out of stack, which would be an issue because that's maybe the 30% of the code that I planned to write
anyway here is my code, I put in the comment what was line 41 (see comment)
#include <vector>
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <fstream>
#include <sstream>
using namespace std;
struct Connection
{
double w;
double dw;
};
class Neuron;
typedef vector<Neuron> Layer;
//*************************** class Neuron ***************
class Neuron
{
public:
Neuron(unsigned numOutput, unsigned MyIndex);
void setOtpuVal(double Val){m_outputVal = Val; }
double getOutputval(void) const {return m_outputVal; }
void feedForward (const Layer &prevLayer);
private:
static double randomWeight(void) {return (rand()/(RAND_MAX));}
unsigned m_MyIndex;
double m_outputVal;
vector<Connection> m_outputWeights;
};
void Neuron::feedForward (const Layer &prevLayer){
double sum = 0.0; //<===================================that's line 40
for (unsigned i = 0; i < prevLayer.size(); ++i)
{
sum += prevLayer[i].getOutputval() * prevLayer[i].m_outputWeights[m_MyIndex].w;
}
}
Neuron::Neuron(unsigned numOutput, unsigned MyIndex){
for (unsigned c = 0; c < numOutput; ++c)
{
m_outputWeights.push_back(Connection());
m_outputWeights.back().w = randomWeight();
}
m_MyIndex = MyIndex;
}
//*************************** class Net *********************
class Net{
public:
Net (const vector<unsigned> &Topology);
void feedForward(const vector<double> &Input );
void backProp (const vector<double> &Target){};
void getResults(vector<double> &Output) const{}; //const non modifica l'oggetto
private:
std::vector<Layer> m_layer; // m_layer []
};
void Net::feedForward (const vector<double> &Input ) {
//assert(Input.size() == m_layer[0].size()-1);
// assert(inputVals.size() == m_layers[0].size() - 1);
//feeding
for (unsigned i = 0; i < Input.size()-1; ++i) {
m_layer [0] [i].setOtpuVal(Input[i]);
}
//foorward propagatin
for (unsigned i = 0; i < m_layer.size(); ++i)
{
Layer &prevLayer = m_layer[i-1];
for (unsigned j = 0; j < m_layer[i].size(); ++j)
{
m_layer[i][j].feedForward(prevLayer);
}
}
}
Net::Net (const vector<unsigned> &Topology){
unsigned numLayer = Topology.size();
for (unsigned i = 0; i < numLayer; ++i)
{
m_layer.push_back(Layer());
unsigned numOutput = i == Topology.size() - 1 ? 0 : Topology[i +1]; //inportante!!!!
for (unsigned j = 0; j <= Topology[i]; ++j)
{
m_layer.back().push_back(Neuron(numOutput,j));
cout<<"made a Neuron"<<endl;
}
}
}
int main(int argc, char const *argv[])
{
ifstream reader("Istruzioni.txt",ios::in);
std::vector<double> Input;
std::vector<double> Target;
std::vector<double> Output;
std::vector<unsigned> Topology;
Topology.push_back(3);
Topology.push_back(2);
Topology.push_back(1);
Net MyNet(Topology);
char letter;
for (int i = 0; i < 4; ++i)
{
reader.get(letter);
if (i == 3)
{
Target.push_back( (float)letter - 48);
}
else
Input.push_back((float)letter - 48);
}
reader.close();
MyNet.feedForward (Input);
MyNet.backProp(Target);
MyNet.getResults(Output);
return 0;
}
The error message and behavior is typical for an invalid memory access. It is one of the possible symptom of UB. So what can be said hereafter is only a probable explanation, but nothing for sure.
Looking at the code, and assuming it was called with a valid prevLayer argument:
for (unsigned i = 0; i < prevLayer.size(); ++i)
{
sum += prevLayer[i].getOutputval() * prevLayer[i].m_outputWeights[m_MyIndex].w;
}
it is with high probability an access out of bounds. Since i is in principle within bounds, so the trouble come m_MyIndex.
What to do ?
Check if that member is properly initialized.
Check if its value is positive and that it's smaller than prevLayer[i].m_outputWeights.size()
If this doesn't help solve the issue, it means that some other place in the code messed up (e.g. prevLayer already refers to an object that doesn't exist, or some memory corruption happened before and didn't show any consequence until this moment).
i'm new in c++ programing and need some help to use a thread library with vector library...
first I follow this tutorial
but the compiler (visual studio 2013) show me errors and I don't know how correct it:
first declaration of function
void Fractal::calcIterThread(vector<vector<iterc>> &matriz, int desdePos, int hastaPos, int idThread){
...
}
in main loop
vector<vector<iterc>> res;
res.resize(altoPantalla);
for (int i = 0; i < altoPantalla; i++){
res[i].resize(anchoPantalla);
}
int numThreads = 10;
vector<thread> workers(numThreads);
for (int i = 0; i < numThreads; i++){ //here diferent try
thread workers[i] (calcIterThread, ref(res), inicio, fin, i)); // error: expresion must have a constant value
workers[i] = thread(calcIterThread, ref(res), inicio, fin, i)); // error: no instance of constructor "std::thread::thread" matches the argument list
}
...rest of code...
thanks for any help to clarify
Try this:
#include <functional>
#include <thread>
#include <vector>
// ...
int numThreads = 10;
std::vector<std::thread> workers;
for (int i = 0; i != numThreads; ++i)
{
workers.emplace_back(calcIterThread, std::ref(res), inicia, fin, i);
}
for (auto & t : workers)
{
t.join();
}
finally I can solve the problem with this change in my code...
workers.emplace_back(thread{ [&]() {
calcIterThread(ref(res), inicio, fin, i);
}});
Below is a small program meant to parallelize the approximation of the 1/(n^2) series. Note the global parameter NUM_THREADS.
My issue is that increasing the number of threads from 1 to 4 (the number of processors my computer has is 4) does not significantly affect the outcomes of timing experiments. Do you see a logical flaw in the ThreadFunction? Is there false sharing or misplaced blocking that ends up serializing the execution?
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <string>
#include <future>
#include <chrono>
std::mutex sum_mutex; // This mutex is for the sum vector
std::vector<double> sum_vec; // This is the sum vector
int NUM_THREADS = 1;
int UPPER_BD = 1000000;
/* Thread function */
void ThreadFunction(std::vector<double> &l, int beg, int end, int thread_num)
{
double sum = 0;
for(int i = beg; i < end; i++) sum += (1 / ( l[i] * l[i]) );
std::unique_lock<std::mutex> lock1 (sum_mutex, std::defer_lock);
lock1.lock();
sum_vec.push_back(sum);
lock1.unlock();
}
void ListFill(std::vector<double> &l, int z)
{
for(int i = 0; i < z; ++i) l.push_back(i);
}
int main()
{
std::vector<double> l;
std::vector<std::thread> thread_vec;
ListFill(l, UPPER_BD);
int len = l.size();
int lower_bd = 1;
int increment = (UPPER_BD - lower_bd) / NUM_THREADS;
for (int j = 0; j < NUM_THREADS; ++j)
{
thread_vec.push_back(std::thread(ThreadFunction, std::ref(l), lower_bd, lower_bd + increment, j));
lower_bd += increment;
}
for (auto &t : thread_vec) t.join();
double big_sum;
for (double z : sum_vec) big_sum += z;
std::cout << big_sum << std::endl;
return 0;
}
From looking at your code, I suspect that ListFill is taking longer than ThreadFunction. Why pass a list of values to the thread instead of the bounds each thread should loop over? Something like:
void ThreadFunction( int beg, int end ) {
double sum = 0.0;
for(double i = beg; i < end; i++)
sum += (1.0 / ( i * i) );
std::unique_lock<std::mutex> lock1 (sum_mutex);
sum_vec.push_back(sum);
}
To maximize parallelism, you need to push as much work as possible onto the threads. See Amdahl's Law
In addition to dohashi's nice improvement, you can remove the need for the mutex by populating the sum_vec in advance in the main thread:
sum_vec.resize(4);
then writing directly to it in ThreadFunction:
sum_vec[thread_num] = sum;
since each thread writes to a distinct element and doesn't modify the vector itself there is no need to lock anything.