Можно ли проверить в Java, является ли процессор гиперпоточным?

Я хотел бы знать оптимальное количество потоков, которые я могу запустить. Обычно это равно Runtime.getRuntime().availableProcessors().

Однако возвращаемое число в два раза больше на ЦП, поддерживающем многопоточность. Так вот, для некоторых задач гиперпоточность хороша, но для других она бесполезна. В моем случае, я подозреваю, это ничего не делает, и поэтому я хочу знать, должен ли я делить число, возвращаемое Runtime.getRuntime().availableProcessors(), на два.

Для этого я должен сделать вывод, является ли процессор гиперпоточным. Отсюда мой вопрос -, как я могу сделать это на Java?

Спасибо.

РЕДАКТИРОВАТЬ

Хорошо, я проверил свой код. Вот мое окружение:

  • Lenovo ThinkPad W510 (, т.е. процессор i7 с 4 ядрами и гиперпоточностью ), 16 ГБ ОЗУ
  • Windows 7
  • 84 заархивированных CSV-файла размером от 105 до 16 МБ
  • . Все файлы читаются один за другим в основном потоке -нет многопоточного доступа к HD.
  • Каждая строка файла CSV содержит некоторые данные, которые анализируются, и быстрый контекст -свободный тест определяет, является ли строка релевантной.
  • Каждая соответствующая строка содержит два двойных значения (, представляющих долготу и широту, для любопытных ), которые преобразуются в один Long, который затем сохраняется в общем наборе хэшей.

Таким образом, рабочие потоки ничего не читают с HD,но они занимаются распаковкой и анализом содержимого (с помощью библиотеки opencsv ).

Ниже приведен код без скучных деталей:

public void work(File dir) throws IOException, InterruptedException {
  Set allCoordinates = Collections.newSetFromMap(new ConcurrentHashMap());
  int n = 6;
  // NO WAITING QUEUE !
  ThreadPoolExecutor exec = new ThreadPoolExecutor(n, n, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue());
  StopWatch sw1 = new StopWatch();
  StopWatch sw2 = new StopWatch();
  sw1.start();
  sw2.start();
  sw2.suspend();
  for (WorkItem wi : m_workItems) {
    for (File file : dir.listFiles(wi.fileNameFilter)) {
      MyTask task;
      try {
        sw2.resume();
        // The only reading from the HD occurs here:
        task = new MyTask(file, m_coordinateCollector, allCoordinates, wi.headerClass, wi.rowClass);
        sw2.suspend();
      } catch (IOException exc) {
        System.err.println(String.format("Failed to read %s - %s", file.getName(), exc.getMessage()));
        continue;
      }
      boolean retry = true;
      while (retry) {
        int count = exec.getActiveCount();
        try {
          // Fails if the maximum of the worker threads was created and all are busy.
          // This prevents us from loading all the files in memory and getting the OOM exception.
          exec.submit(task);
          retry = false;
        } catch (RejectedExecutionException exc) {
          // Wait for any worker thread to finish
          while (exec.getActiveCount() == count) {
            Thread.sleep(100);
          }
        }
      }
    }
  }
  exec.shutdown();
  exec.awaitTermination(1, TimeUnit.HOURS);
  sw1.stop();
  sw2.stop();
  System.out.println(String.format("Max concurrent threads = %d", n));
  System.out.println(String.format("Total file count = %d", m_stats.getFileCount()));
  System.out.println(String.format("Total lines = %d", m_stats.getTotalLineCount()));
  System.out.println(String.format("Total good lines = %d", m_stats.getGoodLineCount()));
  System.out.println(String.format("Total coordinates = %d", allCoordinates.size()));
  System.out.println(String.format("Overall elapsed time = %d sec, excluding I/O = %d sec", sw1.getTime() / 1000, (sw1.getTime() - sw2.getTime()) / 1000));
}

public class MyTask> implements Runnable {
  private final byte[] m_buffer;
  private final String m_name;
  private final CoordinateCollector m_coordinateCollector;
  private final Set m_allCoordinates;
  private final Class m_headerClass;
  private final Class m_rowClass;

  public MyTask(File file, CoordinateCollector coordinateCollector, Set allCoordinates,
                Class headerClass, Class rowClass) throws IOException {
    m_coordinateCollector = coordinateCollector;
    m_allCoordinates = allCoordinates;
    m_headerClass = headerClass;
    m_rowClass = rowClass;
    m_name = file.getName();
    m_buffer = Files.toByteArray(file);
  }

  @Override
  public void run() {
    try {
      m_coordinateCollector.collect(m_name, m_buffer, m_allCoordinates, m_headerClass, m_rowClass);
    } catch (IOException e) {
      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }
  }
}

Пожалуйста, найдите ниже результаты (Я немного изменил вывод, чтобы опустить повторяющиеся части):

Max concurrent threads = 4
Total file count = 84
Total lines = 56395333
Total good lines = 35119231
Total coordinates = 987045
Overall elapsed time = 274 sec, excluding I/O = 266 sec

Max concurrent threads = 6
Overall elapsed time = 218 sec, excluding I/O = 209 sec

Max concurrent threads = 7
Overall elapsed time = 209 sec, excluding I/O = 199 sec

Max concurrent threads = 8
Overall elapsed time = 201 sec, excluding I/O = 192 sec

Max concurrent threads = 9
Overall elapsed time = 198 sec, excluding I/O = 186 sec

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

21
задан mark 31 July 2012 в 13:43
поделиться