I have a vector of 25 elements and I want to process 5 elements concurrently in different threads
But at any time I don't want to create more than 5 thread i.e in one particular time 5 elements will be processed( 0-4, 5-9, 10-14, 15-19, 20-24)
The code is as follows
void test(vector<string> &input){
vector<std::thread> threads;
for(int i=0; i<25;++i){
threads.push_back(std::thread(func, input, i)); //func is a function called by the thread which accepts 2 argument vector<string> and int
if(threads.size()==5){
for (auto &th : threads) {
th.join();
}
threads.clear();
}
}
Here the code will wait till all the 5 thread are completed and then will process for next set
Is there a way to check if any thread gets completed, then a new thread is created but the total count of threads should be <= 5
Related
I have this very simple and small C++ program that creates a thread pool, then put messages in a blocking queue shared between threads to say to each thread what to do.
Message can be: -1 (end of stream -> terminate), -2 (barrier -> wait for all threads to reach it, then continue), other values to do random computation. The loop is done in this order: some computation, barrier, some computation, barrier, ..., barrier, end of stream, thread join, exit.
I'm not able to understand why I obtain deadlock even with 2 threads in the pool. The queue is not able to become empty, but the order in which I push and pop messages would always lead to an empty queue!
The blocking queue implementation is the one proposed here (C++ Equivalent to Java's BlockingQueue) with just two methods added. I copy also the queue code below.
Any help?
Main.cpp
#include <iostream>
#include <vector>
#include <thread>
#include "Queue.hpp"
using namespace std;
// function executed by each thread
void f(int i, Queue<int> &q){
while(1){
// take a message from blocking queue
int j= q.pop();
// if it is end of stream then exit
if (j==-1) break;
// if it is barrier, wait for other threads to reach it
if (j==-2){
// active wait! BAD, but anyway...
while(q.size() > 0){
;
}
}
else{
// random stuff
int x = 0;
for(int i=0;i<j;i++)
x += 4;
}
}
}
int main(){
Queue<int> queue; //blocking queue
vector<thread> tids; // thread pool
int nt = 2; // number of threads
int dim = 8; // number to control number of operations
// create thread pool, passing thread id and queue
for(int i=0;i<nt;i++)
tids.push_back(thread(f,i, std::ref(queue)));
for(int dist=1; dist<=dim; dist++){ // without this outer loop the program works fine
// push random number
for(int j=0;j<dist;j++){
queue.push(4);
}
// push barrier code
for(int i=0;i<nt;i++){
queue.push(-2);
}
// active wait! BAD, but anyway...
while (queue.size()>0){
;
}
}
// push end of stream
for(int i=0;i<nt;i++)
queue.push(-1);
// join thread pool
for(int i=0;i<nt;i++){
tids[i].join();
}
return 0;
}
Queue.hpp
#include <deque>
#include <mutex>
#include <condition_variable>
template <typename T>
class Queue
{
private:
std::mutex d_mutex;
std::condition_variable d_condition;
std::deque<T> d_queue;
public:
void push(T const& value) {
{
std::unique_lock<std::mutex> lock(this->d_mutex);
d_queue.push_front(value);
}
this->d_condition.notify_one();
}
T pop() {
std::unique_lock<std::mutex> lock(this->d_mutex);
this->d_condition.wait(lock, [=]{ return !this->d_queue.empty(); });
T rc(std::move(this->d_queue.back()));
this->d_queue.pop_back();
return rc;
}
bool empty(){
std::unique_lock<std::mutex> lock(this->d_mutex);
return this->d_queue.empty();
}
int size(){
std::unique_lock<std::mutex> lock(this->d_mutex);
return this->d_queue.size();
}
};
I think the problem is your active wait that you describe as "BAD, but anyway..." and using the size of the queue as a barrier instead of using a true synchronization barrier
For dim =1 you push a Queue that has 4, -2, -2. One thread will grab the 4 and -2 while the other grabs the remaining -2. At this point the queue is empty and you have three threads (the two workers and main thread) doing an active wait racing to see if the queue has been emptied. There is a mutex on size that only lets one read the size at a time. If the main thread is scheduled first and determines that queue is empty it will push on -1, -1 to signal end of stream. Now, the queue is no longer empty, but one or both of the two worker threads are waiting for it to empty. Since they are waiting for it to be empty before taking another item the queue is deadlocked in this state.
For the case were dim > 1 there is likely a similar issue with pushing the next set of values into the queue on the main thread before both workings acknowledge the empty the queue and exit the active wait.
I had run your code and I understand the problem. The problem is with "-2" option. When the two threads arrive to this point, your main thread already pushed another values to the queue. So, if your queue increased it's size between the time that your threads got "-2" value, and before they arrive to "-2" option, your code will stuck:
Thread 1: get -2.
Thread 2: get -2.
Thread main: push -1.
Thread main: push -1.
Thread 1: wait untill the whole queue will be empty.
Thread 2: wait untill the whole queue will be empty.
queue:
-1
-1
^ this in case that dim equals 1. In your code, dim equals 8, you don't want to see how it looks like..
To solve this, all I did was to disable the following loop:
for(int i=0;i<nt;i++){
queue.push(-2);
}
When this pard disable, the code run perfectly.
This is how I checked it:
std::mutex guarder;
// function executed by each thread
void f(int i, Queue<int> &q){
while(1){
// take a message from blocking queue
guarder.lock();
int j= q.pop();
guarder.unlock();
// if it is end of stream then exit
if (j==-1) break;
// if it is barrier, wait for other threads to reach it
if (j==-2){
// active wait! BAD, but anyway...
while(q.size() > 0){
;
}
}
else{
// random stuff
int x = 0;
for(int i=0;i<j;i++)
x += 4;
guarder.lock();
cout << x << std::endl;
guarder.unlock();
}
}
}
int main(){
Queue<int> queue; //blocking queue
vector<thread> tids; // thread pool
int nt = 2; // number of threads
int dim = 8; // number to control number of operations
// create thread pool, passing thread id and queue
for(int i=0;i<nt;i++)
tids.push_back(thread(f,i, std::ref(queue)));
for(int dist=1; dist<=dim; dist++){ // without this outer loop the program works fine
// push random number
for(int j=0;j<dist;j++){
queue.push(dist);
}
/*// push barrier code
for(int i=0;i<nt;i++){
queue.push(-2);
}*/
// active wait! BAD, but anyway...
while (queue.size()>0){
;
}
}
// push end of stream
for(int i=0;i<nt;i++)
queue.push(-1);
// join thread pool
for(int i=0;i<nt;i++){
tids[i].join();
}
return 0;
}
The result:
4
8
8
12
12
12
16
16
16
20
20
16
20
20
20
24
24
24
24
24
24
28
28
28
28
28
28
28
32
32
32
32
32
32
32
32
BTW, the stuck didn't occur because your "active wait" part. It is not good, but it cause other problems usually (like slowing down your system).
How can I run a function on a separate thread if a thread is available, assuming that i always want k threads running at the same time at any point?
Here's a pseudo-code
For i = 1 to N
IF numberOfRunningThreads < k
// run foo() on another thread
ELSE
// run foo()
In summary, once a thread is finished it notifies the other threads that there's a thread available that any of the other threads can use. I hope the description was clear.
My personal approach: Just do create the k threads and let them call foo repeatedly. You need some counter, protected against race conditions, that is decremented each time before foo is called by any thread. As soon as the desired number of calls has been performed, the threads will exit one after the other (incomplete/pseudo code):
unsigned int global_counter = n;
void fooRunner()
{
for(;;)
{
{
std::lock_guard g(global_counter_mutex);
if(global_counter == 0)
break;
--global_counter;
}
foo();
}
}
void runThreads(unsigned int n, unsigned int k)
{
global_counter = n;
std::vector<std::thread> threads(std::min(n, k - 1));
// k - 1: current thread can be reused, too...
// (provided it has no other tasks to perform)
for(auto& t : threads)
{
t = std::thread(&fooRunner);
}
fooRunner();
for(auto& t : threads)
{
t.join();
}
}
If you have data to pass to foo function, instead of a counter you could use e. g a FIFO or LIFO queue, whatever appears most appropriate for the given use case. Threads then exit as soon as the buffer gets empty; you'd have to prevent the buffer running empty prematurely, though, e. g. by prefilling all the data to be processed before starting the threads.
A variant might be a combination of both: exiting, if the global counter gets 0, waiting for the queue to receive new data e. g. via a condition variable otherwise, and the main thread continuously filling the queue while the threads are already running...
you can use (std::thread in <thread>) and locks to do what you want, but it seems to me that your code could be simply become parallel using openmp like this.
#pragma omp parallel num_threads(k)
#pragma omp for
for (unsigned i = 0; i < N; ++i)
{
auto t_id = omp_get_thread_num();
if (t_id < K)
foo()
else
other_foo()
}
I am learning about multithreading and I wanted to simulate producer-consumer problem ( using semaphore if I can call it that ).
I have a class that holds a queue, producer push ints into queue and consumer retrieves it and prints it. I simulated is as following
class TestClass{
public:
void producer( int i ){
unique_lock<mutex> l(m);
q.push(i);
if( q.size() )
cnd.notify_all();
}
void consumer(){
unique_lock<mutex> l(m);
while( q.empty() ){
cnd.wait(l);
}
int tmp = q.front();
q.pop();
cout << "Producer got " << tmp << endl;
}
void ConsumerInit( int threads ){
for( int i = 0; i < threads; i++ ){
thrs[i] = thread(&TestClass::consumer, this );
}
for( auto &a : thrs )
a.join();
}
private:
queue<int> q;
vector<thread> thrs;
mutex m;
condition_variable cnd;
};
And I used a little console application to call data:
int main(){
int x;
TestClass t;
int counter = 0;
while( cin >> x ){
if( x == 0 )
break;
if( x == 1)
t.producer(counter++);
if( x == 2 )
t.ConsumerInit(5);
}
}
So when user input 1, a data is pushed into the queue , if user press 2 threads are spawned.
In any order of invoking it, for example, pressing 1 1 and then 2, or 2 1 1
it throws segfault. I am not sure why my understanding of my code is as following: let's assume order 2 1 1
I initialize 5 threads, they see that queue is empty, so they go to sleep. When I push a number to the queue, it notifies all threads sleeping.
The first one to wake up lock mutex again and proceed to retrieve number from queue and afterwards releasing the mutex, when mutex is released another thread do the same and unlocks the mutex, the third thread after mutex is unlocked is still in loop and see that queue is yet again empty and goes to sleep again, same with all remaining threads.
Is this logic correct? If so, why does this keep throwing segfault, if not, I appreciate all explanations.
Thanks for the help!
//edit
By answers suggets , i replaced [] with vector.push_back , but consumer does nothing with data now , does not take it or print it.
You aren't expanding the thrs vector when you do
thrs[i] = thread(&CTest::consumer, this );
You should do
thrs.emplace_back(&CTest::consumer, this);
That's where the crash would be.
Your issue has nothing to do with multithreading. You are accessing a std::vector out-of-bounds:
for (int i = 0; i < threads; i++) {
thrs[i] = thread(&CTest::consumer, this);
//...
vector<thread> thrs;
The thrs vector is empty, and you're trying to access as if it has entries.
To show the error, use:
thrs.at(i) = thread(&CTest::consumer, this);
and you will be greeted with a std::out_of_range exception instead of a segmentation fault.
Your program deadlocks, if the input sequence is not in the form of 1 1 1 1 1 ... 2. That is if the number if 1s preceding 2 is less than five.
Here is the reason:
If the total elements in queue size are less than 5 and the main thread calls consumerInit, some of the five created consumer threads will block waiting for the queue to receive elements. Meanwhile, the main thread blocks on the join operation. Since the main thread will be waiting for consumer threads to finish while some of those threads are waiting for data to consume, there will be no progress. Hence deadlock.
Problem is here:
for( auto &a : thrs )
a.join();
Main thread gets blocked here after you enter 2 waiting for the consumers to finish. So after this point you think that you are entering inputs, while there is no cin happening.
Remove these two lines and then you can enter 1 and producer/consumer will do their job.
I am trying to create a number of different threads that are required to wait for all of the threads to be created before they can perform any actions. This is a smaller part of a large program, I am just trying to take it in steps. As each thread is created it is immediately blocked by a semaphore. After all of the threads have been created, I loop through and release all the threads. I then wish each thread to print out its thread number to verify that they all waited. I only allow one thread to print at a time using another semaphore.
The issue I'm having is that although I create threads #1-10, a thread prints that it is #11. Also, a few threads say they have the same number as another one. Is the error in my passing the threadID or is it in my synchronization somehow?
Here is relevant code:
//Initialize semaphore to 0. Then each time a thread is spawned it will call
//semWait() making the value negative and blocking that thread. Once all of the
//threads are created, semSignal() will be called to release each of the threads
sem_init(&threadCreation,0,0);
sem_init(&tester,0,1);
//Spawn all of the opener threads, 1 for each valve
pthread_t threads[T_Valve_Numbers];
int check;
//Loop starts at 1 instead of the standard 0 so that numbering of valves
//is somewhat more logical.
for(int i =1; i <= T_Valve_Numbers;i++)
{
cout<<"Creating thread: "<<i<<endl;
check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
if(check)
{
cout <<"Couldn't create thread "<<i<<" Error: "<<check<<endl;
exit(-1);
}
}
//Release all of the blocked threads now that they have all been created
for(int i =1; i<=T_Valve_Numbers;i++)
{
sem_post(&threadCreation);
}
//Make the main process wait for all the threads before terminating
for(int i =1; i<=T_Valve_Numbers;i++)
{
pthread_join(threads[i],NULL);
}
return 0;
}
void* Valve_Handler(void* threadNumArg)
{
int threadNum = *((int *)threadNumArg);
sem_wait(&threadCreation);//Blocks the thread until all are spawned
sem_wait(&tester);
cout<<"I'm thread "<<threadNum<<endl;
sem_post(&tester);
}
When T_Valve_Numbers = 10, some sample output is:
Creating thread: 1
Creating thread: 2
Creating thread: 3
Creating thread: 4
Creating thread: 5
Creating thread: 6
Creating thread: 7
Creating thread: 8
Creating thread: 9
Creating thread: 10
I'm thread 11 //Where is 11 coming from?
I'm thread 8
I'm thread 3
I'm thread 4
I'm thread 10
I'm thread 9
I'm thread 7
I'm thread 3
I'm thread 6
I'm thread 6 //How do I have 2 6's?
OR
Creating thread: 1
Creating thread: 2
Creating thread: 3
Creating thread: 4
Creating thread: 5
Creating thread: 6
Creating thread: 7
Creating thread: 8
Creating thread: 9
Creating thread: 10
I'm thread 11
I'm thread 8
I'm thread 8
I'm thread 4
I'm thread 4
I'm thread 8
I'm thread 10
I'm thread 3
I'm thread 9
I'm thread 8 //Now '8' showed up 3 times
"I'm thread..." is printing 10 times so it appears like my semaphore is letting all of the threads through. I'm just not sure why their thread number is messed up.
check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
^^
You're passing the thread start function the address of i. i is changing all the time in the main loop, unsynchronized with the thread functions. You have no idea what the value of i will be once the thread function gets around to actually dereferencing that pointer.
Pass in an actual integer rather than a pointer to the local variable if that's the only thing you'll ever need to pass. Otherwise, create a simple struct with all the parameters, build an array of those (one for each thread) and pass each thread a pointer to its own element.
Example: (assuming your thread index never overflows an int)
#include <stdint.h> // for intptr_t
...
check = pthread_create(..., (void*)(intptr_t)i);
...
int threadNum = (intptr_t)threadNumArg;
Better/more flexible/doesn't require intprt_t that might not exist example:
struct thread_args {
int thread_index;
int thread_color;
// ...
}
// ...
struct thread_args args[T_Valve_Numbers];
for (int i=0; i<T_Valve_Numbers; i++) {
args[i].thread_index = i;
args[i].thread_color = ...;
}
// ...
check = pthread_create(..., &(args[i-1])); // or loop from 0, less surprising
A word of caution about this though: that array of thread arguments needs to stay alive at least as long as the threads will use it. In some situations, you might be better of with a dynamic allocation for each structure, passing that pointer (and its ownership) to the thread function (especially if you're going to detach the threads rather than joining them).
If you're going to join the threads at some point, keep those arguments around the same way you keep your pthread_t structures around. (And if you're creating and joining in the same function, the stack is usually fine for that.)
For example I want each thread to not start running until the previous one has completed, is there a flag, something like thread.isRunning()?
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
void hello() {
cout << "thread id: " << this_thread::get_id() << endl;
}
int main() {
vector<thread> threads;
for (int i = 0; i < 5; ++i)
threads.push_back(thread(hello));
for (thread& thr : threads)
thr.join();
cin.get();
return 0;
}
I know that the threads are meant to run concurrently, but what if I want to control the order?
There is no thread.isRunning(). You need some synchronization primitive to do it.
Consider std::condition_variable for example.
One approachable way is to use std::async. With the current definition of std::async is that the associated state of an operation launched by std::async can cause the returned std::future's destructor to block until the operation is complete. This can limit composability and result in code that appears to run in parallel but in reality runs sequentially.
{
std::async(std::launch::async, []{ hello(); });
std::async(std::launch::async, []{ hello(); }); // does not run until hello() completes
}
If we need the second thread start to run after the first one is completed, is a thread really needed?
For solution I think try to set a global flag, the set the value in the first thread, and when start the second thread, check the flag first should work.
You can't simply control the order like saying "First, thread 1, then thread 2,..." you will need to make use of synchronization (i.e. std::mutex and condition-variables std::condition_variable_any).
You can create events so as to block one thread until a certain event happend.
See cppreference for an overview of threading-mechanisms in C++-11.
You will need to use semaphore or lock.
If you initialize semaphore to value 0:
Call wait after thread.start() and call signal/ release in the end of thread execution function (e.g. run funcition in java, OnExit function etc...)
So the main thread will keep waiting until the thread in loop has completed its execution.
Task-based parallelism can achieve this, but C++ does not currently offer task model as part of it's threading libraries. If you have TBB or PPL you can use their task-based facilities.
I think you can achieve this by using std::mutex and std::condition_variable from C++11. To be able to run threads sequentially array of booleans in used, when thread is done doing some work it writes true in specific index of the array.
For example:
mutex mtx;
condition_variable cv;
int ids[10] = { false };
void shared_method(int id) {
unique_lock<mutex> lock(mtx);
if (id != 0) {
while (!ids[id - 1]) {
cv.wait(lock);
}
}
int delay = rand() % 4;
cout << "Thread " << id << " will finish in " << delay << " seconds." << endl;
this_thread::sleep_for(chrono::seconds(delay));
ids[id] = true;
cv.notify_all();
}
void test_condition_variable() {
thread threads[10];
for (int i = 0; i < 10; ++i) {
threads[i] = thread(shared_method, i);
}
for (thread &t : threads) {
t.join();
}
}
Output:
Thread 0 will finish in 3 seconds.
Thread 1 will finish in 1 seconds.
Thread 2 will finish in 1 seconds.
Thread 3 will finish in 2 seconds.
Thread 4 will finish in 2 seconds.
Thread 5 will finish in 0 seconds.
Thread 6 will finish in 0 seconds.
Thread 7 will finish in 2 seconds.
Thread 8 will finish in 3 seconds.
Thread 9 will finish in 1 seconds.