4

我怀疑这真的很容易,但我不确定在 Java 中是否有一种天真的方法。这是我的问题,我有两个用于处理数据的脚本,它们都有相同的输入/输出,除了一个是为单个 CPU 编写的,另一个是为 GPU 编写的。这项工作来自队列服务器,我正在尝试编写一个程序,根据哪个是空闲的,将数据发送到 CPU 或 GPU 脚本。

我不明白该怎么做。

我知道使用 executorservice 我可以指定要继续运行的线程数,但不确定如何在两个不同的线程之间进行平衡。我在系统上有 2 个 GPU 和 8 个 CPU 内核,我认为我可以让 threadexecutorservice 保持 2 个 GPU 和 8 个 CPU 进程运行,但不确定如何在它们之间取得平衡,因为 GPU 的完成速度比 CPU 任务快得多。

关于如何解决这个问题的任何建议?我应该创建两个队列并继续汇集它们以查看哪个队列不那么忙吗?或者有没有办法把所有的工作单元(都一样)放到一个队列中,让 GPU 或 CPU 进程从同一个队列中取出,因为它们是空闲的?

更新:只是为了澄清。CPU/GPU 程序超出了我正在制作的程序的范围,它们只是我通过两种不同方法调用的脚本。我想我要问的简化版本是两种方法是否可以从同一个队列中工作?

4

4 回答 4

2

两种方法可以从同一个队列中工作吗?

是的,但是您应该使用 aBlockingQueue来为自己节省一些同步心痛。

基本上,一种选择是让生产者通过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...
于 2013-02-12T07:39:31.580 回答
1

像这样使用 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。使用两个工作人员设置一个 ThreadPoolExecutor。确保 Threadfactory 创建一个 CPU,然后创建一个 GPU 线程实例。

于 2013-02-11T17:02:06.850 回答
1

显然有不止一种方法可以做到这一点,通常最简单的就是最好的。我建议线程池,一个有 2 个线程用于 CPU 任务,第二个有 8 个线程将运行 GPU 任务。您的工作单元经理可以将工作提交到当前具有空闲线程的池中(我建议同步该代码块)。标准 Java ThreadPoolExecutor 具有 getActiveCount() 方法,您可以使用它,请参阅 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#getActiveCount()

于 2013-02-11T17:07:09.563 回答
1

我想你有两个代表两个 GPU 的对象,它们的方法类似于boolean isFree()void execute(Runnable)。然后你应该启动 8 个线程,它们在一个循环中从队列中获取下一个作业,如果有的话,将它放在一个空闲的 GPU 中,否则执行作业本身。

于 2013-02-12T07:22:50.493 回答