[英]Balancing multiple queues
我怀疑这很容易,但我不确定在Java中是否有一种天真的方式。 这是我的问题,我有两个处理数据的脚本,两个都有相同的输入/输出,除了一个写入单CPU,另一个写入GPU。 这项工作来自队列服务器,我正在尝试编写一个程序,将数据发送到CPU或GPU脚本,具体取决于哪一个是免费的。
我不明白该怎么做。
我知道使用executorservice我可以指定我想继续运行多少个线程,但不知道如何在两个不同的线程之间取得平衡。 我在系统上有2个GPU和8个CPU内核,并认为我可以让threadexecutorservice保持2个GPU和8个CPU进程运行,但不确定如何在它们之间取得平衡,因为GPU将比CPU任务更快地完成。
有关如何处理此问题的任何建议? 我应该创建两个队列并继续汇集它们以查看哪个队列不太忙吗? 或者有没有办法将所有工作单元(都是相同的)放入一个队列,并让GPU或CPU进程从同一个队列获取,因为它们是免费的?
更新:只是为了澄清。 CPU / GPU程序超出了我正在制作的程序范围,它们只是我通过两种不同方法调用的脚本。 我想我所问的简化版是两个方法可以从同一个队列中工作吗?
两个方法可以从同一个队列中工作吗?
是的,但你应该使用BlockingQueue
来节省一些同步心痛。
基本上,一个选项是让生产者通过BlockingQueue.offer
将任务放入队列。 然后设计你的CPU / GPU线程来调用BlockingQueue.take
并对它们收到的任何内容执行工作。
例如:
main (...) {
BlockingQueue<Task> queue = new LinkedBlockingQueue<>();
for (int i=0;i<CPUs;i++) {
new CPUThread(queue).start();
}
for (int i=0;i<GPUs;i++) {
new GPUThread(queue).start();
}
for (/*all data*/) {
queue.offer(task);
}
}
class CPUThread {
public void run() {
while(/*some condition*/) {
Task task = queue.take();
//do task work
}
}
}
//etc...
像这样使用Runnables:
CPUGPURunnable implements Runnable {
run() {
if ( Thread.currentThread() instance of CPUGPUThread) {
CPUGPUThread t = Thread.currentThread();
if ( t.isGPU())
runGPU();
else
runCPU();
}
}
}
CPUGPUThreads是一个Thread子类,它使用标志知道它是在CPU还是GPU模式下运行。 为ThreadPoolExecutors创建一个ThreadFactory,创建一个GPU线程的CPU。 设置一个包含两个worker的ThreadPoolExecutor。 确保Threadfactory创建一个CPU,然后创建一个GPU线程实例。
显然,有不止一种方法可以做到这一点,通常最简单的方法是最好的。 我建议使用线程池,一个用于CPU任务的2个线程,第二个用于8个线程的线程池将运行GPU任务。 您的工作单位经理可以将工作提交到当前具有空闲线程的池(我建议同步该代码块)。 标准Java ThreadPoolExecutor具有可用于它的getActiveCount()方法,请参阅http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#getActiveCount() 。
我想你有两个代表两个GPU的对象,其方法有boolean isFree()
和void execute(Runnable)
。 然后你应该启动8个线程,它们在循环中从队列中获取下一个作业,将其放入一个免费的GPU,如果有的话,否则执行作业本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.