2016-12-26 29 views
0

Я использую компилятор Intel C++ 17.0.01, и у меня есть два блока кода.Перевод отладки Intel®pragma для OpenMP для Xeon Phi (проблемы с производительностью и другие вопросы)

Первый блок кода выделяет память на Xeon Phi, как это:

#pragma offload target(mic:1) nocopy(data[0:size]: alloc_if(1) free_if(0)) 

Второй блок оценивает выше память и копирует его обратно к хозяину:

#pragma offload target(mic:1) out(data[0:size]: alloc_if(0) free_if(0)) 

Этот код работает нормально но разгрузка #pragma является частью компилятора Intel (я думаю). Итак, я хочу преобразовать это в OpenMP.

Это, как я перевел первый блок в OpenMP:

#pragma omp target device(1) map(alloc:data[0:size]) 

И это, как я перевел второй блок в OpenMP:

#pragma omp target device(1) map(from:data[0:size]) 

Кроме того, я использовал export OFFLOAD_REPORT=2 для того, чтобы получить лучшая идея о том, что происходит во время работы.

Вот мои проблемы/вопросы:

  • версия OpenMP первого блока кода является так же быстро, как версия Intel (#pragma offload). Здесь ничего странного.
  • Версия второго кода блока OpenMP в 5 раз медленнее, чем версия Intel. Тем не менее, MIC_TIME двух одинаковых, но CPU_TIME отличается (версия OpenMP намного выше). Почему это?
  • Является ли мои директивы Intel оптимальными?
  • Является ли мой Intel -> OpenMP-перевод правильным и оптимальным?

А вот некоторые другие, немного по-другому, вопросы:

  • На испытательной машине у меня есть две карты Intel Phi. Поскольку я хочу использовать второй, я делаю это: #pragma omp target device(1).... Это верно?
  • Если я делаю #pragma omp target device(5)... код все еще работает! И он работает на одной из Phi-карт (а не на процессоре), потому что производительность похожа. Почему это?
  • Я также попробовал свое программное обеспечение (версия OpenMP) на машине без Xeon Phi, и он отлично работает на процессоре! Это гарантировано? Когда у вас нет ускорителя на машине, target device(1) игнорируется?
  • Возможно ли сделать что-то вроде std::cout << print_phi_card_name_or_uid(); внутри загруженной области OpenMP (так что я точно знаю, в какой программе работает мое программное обеспечение)?

ответ

0

Второй блок кода OpenMP снова выделяет память. Вы должны сопоставить данные в среду данных устройства, включив оба блока в #pragma omp target data map(from:data[0:size]) или просто добавьте #pragma omp target enter data map(alloc:data[0:size]) до первого блока.

На испытательной машине у меня две карты Intel Phi. Поскольку я хочу использовать второй, я делаю это: #pragma omp target device (1) .... Это правильно?

AFAIK, устройство (0) означает карточку по умолчанию, устройство (1) означает первую карту, а устройство (2) - вторая карта.

Если я использую целевое устройство #pragma omp (5) ... код все еще работает! И он работает на одной из Phi-карт (а не на процессоре), потому что производительность похожа. Почему это?

Поскольку liboffload does this (liboffload - это библиотека времени выполнения, используемая как gcc, так и icc). Однако стандарт OpenMP не гарантирует такого поведения.

Я также попробовал свое программное обеспечение (версия OpenMP) на машине без Xeon Phi, и он работает очень хорошо на процессоре! Это гарантировано? Когда у вас нет ускорителя на аппарате, целевое устройство (1) игнорируется?

Да. Не уверен в стандарте, но разгрузка в icc и gcc реализована таким образом.

Можно ли сделать что-то вроде станд :: COUT < < print_phi_card_name_or_uid(); внутри загруженного региона OpenMP (так что я точно знаю, в какой программе работает мое программное обеспечение)?

OpenMP 4.5 обеспечивает только функцию omp_is_initial_device(), чтобы различать хост и ускоритель. Возможно, для этого есть определенный интерфейс, специфичный для Intel.