Я запускаю Ubuntu на машине с четырехъядерным процессором. Я написал некоторый тестовый Java-код, который порождает определенное количество процессов, которые просто увеличивают изменчивую переменную для заданного количества итераций при запуске.
Я ожидал бы, что время выполнения не увеличится значительно, а количество потоков меньше или равно числу ядер, т.е. 4. Фактически, это время, когда я получаю "реальное время" из UNIX time
:
1 thread: 1.005s
2 потока: 1.018s
3 темы: 1.528s
4 потока: 1.982s
5 нитей: 2.479s
6 нитей: 2.934s
7 потоков: 3.356s
8 нитей: 3.793s
Это показывает, что добавление одного дополнительного потока не увеличивает время, как ожидалось, но тогда время увеличивается с 3 и 4 потоками.
Сначала я думал, что это может быть связано с тем, что ОС препятствует использованию JVM всех ядер, но я побежал top
, и он ясно показал, что с 3 потоками 3 ядра работали на ~ 100%, а с 4 потока, 4 ядра были превышены.
Мой вопрос: почему код работает на 3/4 процессорах не примерно такой же, как при работе на 1/2? Поскольку он работает параллельно на всех ядрах.
Вот мой основной метод для справки:
class Example implements Runnable {
// using this so the compiler does not optimise the computation away
volatile int temp;
void delay(int arg) {
for (int i = 0; i < arg; i++) {
for (int j = 0; j < 1000000; j++) {
this.temp += i + j;
}
}
}
int arg;
int result;
Example(int arg) {
this.arg = arg;
}
public void run() {
delay(arg);
result = 42;
}
public static void main(String args[]) {
// Get the number of threads (the command line arg)
int numThreads = 1;
if (args.length > 0) {
try {
numThreads = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
System.out.println("First arg must be the number of threads!");
}
}
// Start up the threads
Thread[] threadList = new Thread[numThreads];
Example[] exampleList = new Example[numThreads];
for (int i = 0; i < numThreads; i++) {
exampleList[i] = new Example(1000);
threadList[i] = new Thread(exampleList[i]);
threadList[i].start();
}
// wait for the threads to finish
for (int i = 0; i < numThreads; i++) {
try {
threadList[i].join();
System.out.println("Joined with thread, ret=" + exampleList[i].result);
} catch (InterruptedException ie) {
System.out.println("Caught " + ie);
}
}
}
}