Question

I'm working on a library doing audio encoding/decoding. The encoder shall be able to use multiple cores (i.e. multiple threads, using boost library), if available. What i have right now is a class that performs all encoding-relevant operations.

The next step i want to take is to make that class threaded. So i'm wondering how to do this.

I thought about writing a thread-class, creating n threads for n cores and then calling the encoder with the appropriate arguments. But maybe this is an overkill and there is no need for another class, so i'm going to make use of the "user interface" for thread-creation.

I hope there are any suggestions.

Edit: I'm forced to use multiple threads for the pre-processing, creating statistics of the input data using CUDA. So, if there are multiple Cards in a system the only way to use them in parallel is to create multiple threads.

Example: 4 Files, 4 different calculation units (separate memories, unique device id). Each of the files shall be executed on one calculation unit.

What i have right now is:

class Encoder {
[...]
public:
    worker(T data, int devId);
[...]
}

So i think the best way is to call worker from threaded from main()

boost::thread w1(&Encoder::worker, data0, 0);
boost::thread w2(&Encoder::worker, data1, 1);
boost::thread w3(&Encoder::worker, data2, 2);
boost::thread w4(&Encoder::worker, data3, 3);

and not to implement a thread-class.

Was it helpful?

Solution

I think the problem is more at a design level, can you elaborate a bit on what classes do you have ? I work on CUDA too, and usually one creates an interface (aka Facade pattern) for using the architecture specific (CUDA) layer.

Edit: After reading the update interface I think you are doing the right thing. Keep the Encoder logic inside the class and use plain boost::threads to execute different units of work. Just pay attention on thread safety inside Encoder's methods.

OTHER TIPS

Have a look at OpenMP, if your compiler supports it. It can be as easy as adding a compiler flag and spraying on a few #pragmas.

Your current suggestion only works if Encoder::worker is static. I assume that is the case. One concern would be, if your current implementation supports a way to gracefully abort an encoding-job. I suppose there is some method in your code of the form:

while( MoreInputSamples ) {
    // Do more encoding
}

This may be modified with some additional condition that checks if the jobs has received an abort signal. I work on video-decoding a lot and i like to have my decoder classes like that:

class Decoder {
public:
    void DoOneStepOfDecoding( AccessUnit & Input );
}

The output usually goes to some ring-buffer. This way, I can easily wrap this in both single-and multithreaded scenarios.

The preceding code

  boost::thread w1(&Encoder::worker, data0, 0);

is not valid until worker is static.

There is Boost.Task on th review Schedule that allows you to call asynchronously any callable, as follows

  boost::tasks::async(
    boost::tasks::make_task( &Encoder::worker, data0, 0) ) );

This results in Encoder::worker been called on a default threadpool. The function returns a handle that allows to know when the task has been executed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top