2013-02-11 2 views
4

Я подозреваю, что это очень просто, но я не уверен, есть ли наивный способ сделать это на Java. Вот моя проблема: у меня есть два сценария для обработки данных, и оба имеют одинаковые входы/выходы, за исключением того, что один написан для одного процессора, а другой для графических процессоров. Работа происходит от сервера очереди, и я пытаюсь написать программу, которая отправляет данные либо на процессор, либо на графический процессор, в зависимости от того, какой из них является бесплатным.Балансировка нескольких очередей

Я не понимаю, как это сделать.

Я знаю, что с помощью executorservice Я могу указать, сколько потоков я хочу продолжать работать, но не уверен, как сбалансировать между двумя разными. У меня есть 2 GPU и 8 ядер процессора в системе, и я думал, что у меня может быть трэдексрексерсервис, который поддерживает 2 процессора GPU и 8 процессоров, но не уверен, как сбалансировать их, поскольку GPU будет выполняться намного быстрее, чем задачи CPU.

Любые предложения о том, как подойти к этому? Должен ли я создавать две очереди и собирать их, чтобы увидеть, какой из них менее занят? или есть способ просто поместить все рабочие единицы (все-таки) в одну очередь и выполнить процесс GPU или CPU из той же очереди, что и они, бесплатно?

ОБНОВЛЕНИЕ: только для уточнения. программы CPU/GPU выходят за рамки программы, которую я создаю, это просто сценарии, которые я вызываю двумя различными способами. Я предполагаю, что упрощенная версия того, что я прошу, заключается в том, что два метода могут выполнять работу из одной очереди?

+2

Не знаете, как использовать GPU, но вы не можете просто 10 потоков (в ExecutorService или 2 - не уверен, что ГПУ часть) работает что-то вроде 'в то время как (true) {Задача t = yourQueue.take(); t.run();} '?Поэтому каждый поток может идти и выполнять новую задачу, когда это делается, независимо от того, что делают другие. – assylias

+0

@assylias Я не уверен, что полностью понимаю (я, возможно, и не объяснил это правильно). Если у меня есть два метода, как они могут получать данные из одной очереди с помощью кода примера? Разве это не просто отправить всю работу одному методу? (извините, что я новичок на Java, но я пока не понимаю). – Lostsoul

ответ

2

Может ли два метода взять работу из одной очереди?

Да, но вы должны использовать 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... 
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, используя флаг. Имейте ThreadFactory для ThreadPoolExecutors, который создает либо процессор потока GPU. Настройте ThreadPoolExecutor с двумя рабочими. Убедитесь, что Threadfactory создает процессор, а затем экземпляр потока GPU.

+0

... runCPU и runGPU - это ваши два метода отправки заданий на GPU или их использование на CPU. –

+0

Я предполагал, что вы хотите выполнить одно задание CPU и одно задание графического процессора параллельно в любой момент времени. Конечно, если у вас более одного ядра, а runCPU - однопоточное, используйте больше работников. То же самое для GPU. –

1

Очевидно, что существует более чем один способ сделать это, как правило, самым простым является лучшее. Я бы предложил threadpools, один с 2 потоками для задач CPU, второй с 8 потоками будет запускать задачи GPU. Менеджер рабочего места может отправить работу в пул, в котором сейчас нет потоков (я бы рекомендовал синхронизировать этот блок кода). Стандартный Java ThreadPoolExecutor имеет метод getActiveCount(), который вы можете использовать для него, см. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#getActiveCount().

1

Предположим, у вас есть два объекта, представляющих два графических процессора, с такими методами, как boolean isFree() и void execute(Runnable). Затем вы должны запустить 8 потоков, которые в цикле принимают очередное задание из очереди, помещают его в свободный графический процессор, если таковой имеется, в противном случае выполняют задание.

Смежные вопросы