Tarun Gehlaut
Tarun Gehlaut

Reputation: 1342

C++: Multi-thread design when each thread is supposed to do both I/O and CPU intensive task

I have a situation where I am offloading my work to threads. The "work" compromises of two portions:

My main thread is continuously creating many data buffers.

I was initially thinking of a thread pool design, but then there could be a possibility that all my threads in the pool are waiting on I/O.

If I create a new thread whenever I create a new dataBuffer, I see that a large number of threads get created. This can then have overhead of content switching, but because of the context switch my CPU cycles are not getting wasted.

What can be a good design to manage this situations?

Upvotes: 1

Views: 178

Answers (3)

Adi Levin
Adi Levin

Reputation: 5233

Another useful and highly efficient design pattern, is to have a pool of threads all pulling from a single queue of tasks. Each task, upon completion, generates a new task and pushes it to the queue

The data generation task, upon completion, generates the compression task. The compression task, upon completion, generates the storage task.

Now, if you want all storage tasks to happen sequentially, use a separate queue for those, and have just one dedicated thread pulling tasks from that queue.

The advantage is that this creates a very clean and general design, in which direct message passing is avoided, and instead a concurrent queue provides the reliability, and there's minimal context switching. It is highly scalable, because it will always make use of as many threads as you have in the pool. This is optimal in case you don't have any order constraints (such as "buffer #n must be written to disk before buffer #(n+1)").

Upvotes: 1

Jack
Jack

Reputation: 46

I think you can use 2 semaphore variables to sync the worker thread. For example the variables is:

  • compressSemaphore:
  • storeSemaphore:

And you also need 2 queue to store the data:

  • toCompressData:
  • toStoreData:

Your main thread is creating many data buffers, and then put the data buffer into toCompressData and signal the compressSemaphore.

Your compress worker thread is wait for compressSemaphore, and start to get data from toCompressData if get a signal from main thread. The compress thread will put the compressed data into toStoreData, and signal storeSemaphore.

Your store worker thread is wait for storeSemaphore, and start to get data from toStoreData if the semaphore is signal.

You can set fixed number of compress worker thread or store thread, or can adjust the number dynamically.

Upvotes: 0

DrunkenMaster
DrunkenMaster

Reputation: 1278

Let me try if i could help for this.

1. First compress the given data buffer
2. Then write the compressed data to disk

What i understand from you is you have data buffer generated, which you need to compress and store into the disk.

If order matters and source of data is not time intensive that it will not loose the data till the next cycle, then you could have the below approach.

Thread A

Generate a data buffer

Signal to Thread B saying you have a data.

Thread B

Wait for the signal from Thread A

Retrieve the data and compress.

Signal to Thread C to store it.

Thread C

Wait for the signal from Thread B

Retrieve compressed data, and store into the disk.

Upvotes: 1

Related Questions