0

I am trying to write code for finding if pairwise sums are even or not(among all possible pairs from 0 to 100000). I have written code using pthreads where the work allocation is done statically. Here is the code

#include<iostream>
#include<chrono>
#include<iomanip>
#include<pthread.h>


using namespace std;
#define MAX_THREAD 4

vector<long long> cnt(MAX_THREAD,0);
long long n = 100000;
int work_per_thread;

void *count_array(void* arg)
{
    int t = *((int*)arg);
    long long sum = 0;
    int counter = 0;
    for(int i = t*work_per_thread + 1; i <= (t+1)*work_per_thread; i++)
      for(int j = i-1; j >= 0; j--)
      {
         sum = i + j;
         if(sum%2 == 0)
             counter++;
      }
    cnt[t] = counter;
    cout<<"thread"<<t<<" finished work"<<endl;
    return NULL;
}


int main()
{
  pthread_t threads[MAX_THREAD];
  vector<int> arr;
  for(int i = 0; i < MAX_THREAD; i++)
    arr.push_back(i);
  long long total_count = 0;
  work_per_thread = n/MAX_THREAD;

  auto start = chrono::high_resolution_clock::now();
  for (int i = 0; i < MAX_THREAD; i++)
      pthread_create(&threads[i], NULL, count_array, &arr[i]);

  for (int i = 0; i < MAX_THREAD; i++)
      pthread_join(threads[i], NULL);

  for (int i = 0; i < MAX_THREAD; i++)
      total_count += cnt[i];

  cout << "count is " << total_count << endl;

  auto end = chrono::high_resolution_clock::now();
  double time_taken = chrono::duration_cast<chrono::nanoseconds>(end - start).count();
  time_taken *= 1e-9;
  cout << "Time taken by program is : " << fixed << time_taken << setprecision(9)<<" secs"<<endl;

  return 0;
}

Now I want to do the work allocation part dynamically. To be specific, let's say I have 5 threads. Initially I give the threads a certain range to work with, let's say thread1 works on all pairs from 0-1249, thread2 from 1250-2549 and so on. Now as soon as a thread completes its work I want to give it a new range to work on. This way no threads will be idle for most of the time, like was in the case of static allocation.

Mr.Gen
  • 33
  • 4
  • Try to find a [library])(https://stackoverflow.com/a/25684747/4123703) before you make your own thread-pool. – Louis Go Aug 08 '22 at 05:29
  • 1
    Threadpools are quite hard to get right (specially at shutdown). Also don't use pthread, since C++11 there is std::async (or std::thread). And some of the stl algorithms already have a parallel implementation e.g. : https://en.cppreference.com/w/cpp/algorithm/for_each (call with parallel execution strategy). – Pepijn Kramer Aug 08 '22 at 06:00

1 Answers1

1

This is the classic usage of a thread pool. Typically you set up a synchronized queue that can be pushed and pulled by any number of threads. Then you start N threads, the "thread pool". These threads wait on a condition variable that locks a mutex. When you have work to do from the main thread, it pushes work into the queue (it can be as simple as a struct with a range) and then signals the condition variable, which will release one thread.

See this answer: https://codereview.stackexchange.com/questions/221617/thread-pool-c-implementation

Something Something
  • 3,999
  • 1
  • 6
  • 21
  • That does not look like a good thread pool implementation. Why suggest someone’s side project, rather than something well-implemented and mature like Intel TBB, or CTPL? – Sneftel Aug 08 '22 at 05:54