Balancing multiple queues

I suspect this is very simple, but I'm not sure if this is a naive way to do this in Java. Heres my problem, I have two scenarios for processing data, and both have the same I / O, except that one is written for one processor and the other for GPUs. The work comes from the queue server, and I'm trying to write a program that sends data to a CPU or GPU script, depending on which one is free.

I don’t understand how to do this.

I know that with the help of the executorservice I can specify how many threads I want to keep working, but I'm not sure how to balance between two different ones. I have 2 GPUs and 8 processor cores in the system, and I thought that I would have support for three processors and 8 processors, but are not sure how to balance them, since the GPU will run much faster than the CPU tasks.

Any suggestions on how to approach this? Do I have to create two lines and collect them to see which one is less busy? or is there a way to simply put all the work units (after all) in one queue and execute the GPU or CPU process from one queue, since they are free?

UPDATE: just clarify. CPU / GPU programs go beyond the scope of the program I create, these are just scripts that I invoke in two different ways. I assume that a simplified version of what I am asking is that two methods can work from the same queue?

+4
source share
4 answers

Can two methods work from the same queue?

Yes, but you should use BlockingQueue to keep yourself some heartache in sync.

Basically, one option would be to have a manufacturer that queues tasks through BlockingQueue.offer . Then create CPU / GPU threads to call BlockingQueue.take and do the work on what they get.

For instance:

 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... 
+2
source

Use Runnables as follows:

 CPUGPURunnable implements Runnable { run() { if ( Thread.currentThread() instance of CPUGPUThread) { CPUGPUThread t = Thread.currentThread(); if ( t.isGPU()) runGPU(); else runCPU(); } } } 

CPUGPUThreads is a subclass of Thread that knows if it works in CPU or GPU mode using a flag. Have a ThreadFactory for ThreadPoolExecutors, which creates either a GPU thread processor. Configure ThreadPoolExecutor with two workers. Make sure Threadfactory creates the processor, and then the GPU thread instance.

+1
source

Obviously, there is more than one way to do this, usually the easiest. I would suggest threadpools, one with 2 threads for CPU tasks, the second with 8 threads will run GPU tasks. The workplace manager can send work to a pool in which there are currently no threads (I would recommend synchronizing this block of code). The standard Java ThreadPoolExecutor has a getActiveCount () method that you can use for it, see http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#getActiveCount () .

+1
source

I assume that you have two objects representing two GPUs, with methods such as boolean isFree() and void execute(Runnable) . Then you must start 8 threads, which in the cycle take the next task from the queue, put it in a free graphics processor, if there is one, otherwise they perform the task itself.

+1
source

All Articles