Как удостовериться, что потоки Java работают на различных ядрах

Я пишу многопоточное приложение в Java для улучшения производительности по последовательной версии. Это - параллельная версия решения для динамического программирования 0/1 задачи о ранце. У меня есть Intel Core 2 Duo и с Ubuntu и с Windows 7 Professional на различных разделах. Я работаю в Ubuntu.

Моя проблема состоит в том, что параллельная версия на самом деле занимает больше времени, чем последовательная версия. Я думаю, что это может быть то, потому что потоки все отображаются на том же потоке ядра или что они выделяются тому же ядру. Существует ли способ, которым я мог удостовериться, что каждый поток Java отображается на отдельное ядро?

Я прочитал другие сообщения об этой проблеме, но ничто, кажется, не помогает.

Вот конец основных () и все выполненные () для класса KnapsackThread (который расширяет Поток). Заметьте, что они, способ, которым я использую часть и дополнительный для вычисления myLowBound и myHiBound, гарантирует, что каждый поток не наложится в домене dynProgMatrix. Поэтому не будет никаких условий состязания.

    dynProgMatrix = new int[totalItems+1][capacity+1];
    for (int w = 0; w<= capacity; w++)
        dynProgMatrix[0][w] = 0;
    for(int i=0; i<=totalItems; i++)
        dynProgMatrix[i][0] = 0;
    slice = Math.max(1,
            (int) Math.floor((double)(dynProgMatrix[0].length)/threads.length));
    extra = (dynProgMatrix[0].length) % threads.length;

    barrier = new CyclicBarrier(threads.length);
    for (int i = 0; i <  threads.length; i++){
        threads[i] = new KnapsackThread(Integer.toString(i));
    }
    for (int i = 0; i < threads.length; i++){
        threads[i].start();
    }

    for (int i = 0; i < threads.length; i++){
        try {
            threads[i].join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void run(){
    int myRank = Integer.parseInt(this.getName());

    int myLowBound;
    int myHiBound;

    if (myRank < extra){
        myLowBound = myRank * (slice + 1);
        myHiBound = myLowBound + slice;
    }
    else{
        myLowBound = myRank * slice + extra;
        myHiBound = myLowBound + slice - 1;
    }

    if(myHiBound > capacity){
        myHiBound = capacity;
    }

    for(int i = 1; i <= totalItems; i++){
        for (int w = myLowBound; w <= myHiBound; w++){

            if (allItems[i].weight <= w){
               if (allItems[i].profit + dynProgMatrix[i-1][w-allItems[i].weight]
                        > dynProgMatrix[i-1][w])
                {
                    dynProgMatrix[i][w] = allItems[i].profit +
                                      dynProgMatrix[i-1][w- allItems[i].weight];
                }
                else{
                    dynProgMatrix[i][w] = dynProgMatrix[i-1][w];
                }
            }
            else{
                dynProgMatrix[i][w] = dynProgMatrix[i-1][w];
            }
        }
        // now place a barrier to sync up the threads
        try {
            barrier.await(); 
        } catch (InterruptedException ex) { 
            ex.printStackTrace();
            return;
        } catch (BrokenBarrierException ex) { 
            ex.printStackTrace(); 
            return;
        }
    }
}

Обновление:

Я записал другую версию ранца, который использует грубую силу. Эта версия имеет очень мало синхронизации, потому что я только должен обновить bestSoFar переменную в конце выполнения единственного потока. Поэтому каждый поток в значительной степени должен выполниться полностью параллельно за исключением того маленького критического раздела в конце.

Я выполнил это по сравнению с последовательной грубой силой, и тем не менее она занимает больше времени. Я не вижу никакое другое объяснение, чем это, мои потоки выполняются последовательно, или потому что они отображаются на том же ядре или на том же собственном потоке.

У кого-либо есть понимание?

13
задан Michael Myers 16 February 2010 в 22:42
поделиться

2 ответа

Сомневаюсь, что это будет связано с использованием одного и того же ядра для всех потоков. Планирование зависит от операционной системы, но вы должны иметь возможность увидеть, что происходит, если вы поднимете менеджер производительности операционной системы - это, как правило, покажет, насколько занято каждое ядро.

Возможные причины, по которым это занимает больше времени:

  • Много синхронизации (необходимой или ненужной)
  • Задачи, требующие столь короткого времени, что создание потоков занимает значительную часть времени
  • Переключение контекста, если вы создаете слишком много потоков - для задач, требующих интенсивного использования процессора, создайте столько потоков, сколько у вас есть ядер.
21
ответ дан 1 December 2019 в 20:57
поделиться

Я предлагаю вам посмотреть, сколько времени требуется каждому из ваших рабочих потоков, прежде чем они завершатся. Возможно, у одного из потоков гораздо более сложная задача. Если это так, то накладные расходы, вызванные синхронизацией и т. Д., Легко съедят то, что вы получили от многопоточности.

1
ответ дан 1 December 2019 в 20:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: