我正在开发一个进行音频编码/解码的库。如果可用,编码器应能够使用多个核(即多个线程,使用升压库)。我现在拥有的是一个执行所有编码相关操作的类。
我想采取的下一步是使该类具有线程。所以我想知道如何做到这一点。
我考虑过编写一个线程类,为n个内核创建n个线程,然后使用适当的参数调用编码器。但也许这是一个矫枉过正,并且不需要另一个类,所以我将利用“用户界面”进行线程创建。
我希望有任何建议。
编辑:我被迫使用多个线程进行预处理,使用CUDA创建输入数据的统计信息。因此,如果系统中有多个卡,并行使用它们的唯一方法是创建多个线程。
示例: 4个文件,4个不同的计算单位(单独的内存,唯一的设备ID)。每个文件都应在一个计算单元上执行。
我现在拥有的是:
class Encoder {
[...]
public:
worker(T data, int devId);
[...]
}
所以我认为最好的方法是从main()
中调用workerboost::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);
而不是实现线程类。
答案 0 :(得分:2)
如果您的编译器支持,请查看OpenMP。它可以像添加编译器标志和喷涂几个#pragma
一样简单。
答案 1 :(得分:1)
我认为问题更多的是设计层面,你能详细说明你有什么课吗?我也在使用CUDA,通常会创建一个接口(也就是Facade模式)来使用特定于体系结构(CUDA)的层。
编辑:阅读更新界面后,我认为您做的是正确的。 将Encoder逻辑保留在类中,并使用普通的boost :: threads来执行不同的工作单元。只需关注编码器方法中的线程安全性。
答案 2 :(得分:1)
您当前的建议仅在Encoder::worker
为static
时才有效。我认为是这样的。如果您当前的实现支持一种优雅地中止编码作业的方法,那么问题就在于此。我想你的代码中有一些方法:
while( MoreInputSamples ) {
// Do more encoding
}
可以使用一些附加条件修改此操作,以检查作业是否已收到中止信号。我经常进行视频解码,我喜欢这样的解码器类:
class Decoder {
public:
void DoOneStepOfDecoding( AccessUnit & Input );
}
输出通常会转到某个环形缓冲区。这样,我可以轻松地将其包装在单线程和多线程场景中。
答案 3 :(得分:1)
前面的代码
boost::thread w1(&Encoder::worker, data0, 0);
在工人静止之前无效。
审核时间表中有Boost.Task允许您异步调用任何可调用的内容,如下所示
boost::tasks::async(
boost::tasks::make_task( &Encoder::worker, data0, 0) ) );
这会导致在默认的线程池上调用Encoder :: worker。该函数返回一个句柄,允许知道任务何时执行。