Почему компилятор Intel игнорирует прагматическую директиву невременной предварительной выборки для Intel MIC?

Компилятор Intel генерирует следующую инструкцию предварительной выборки в цикле для доступа к массиву a_ptr указатель:

400e93:       62 d1 78 08 18 4c 24    vprefetch0 [r12+0x80]

Если я вручную изменю (путем шестнадцатеричного редактирования исполняемого файла) это на временную предварительную выборку:

400e93:       62 d1 78 08 18 44 24    vprefetchnta [r12+0x80]

цикл работает почти в 1,5 раза быстрее (!!!). Однако я бы предпочел, чтобы компилятор генерировал для меня временную предварительную выборку. я думал так

#pragma prefetch a_ptr:_MM_HINT_NTA

до цикла должен сделать трюк, но на самом деле это не так; он генерирует те же самые инструкции, что и без прагмы. Зачем icpc игнорирует эту прагму? Как я могу заставить его генерировать невременное предварительное обучение?

Оптик Отчет не говорит ничего полезного, насколько я вижу:

LOOP BEGIN at test-mic.cpp(56,5)
remark #15344: loop was not vectorized: vector dependence prevents vectorization
remark #15346: vector dependence: assumed ANTI dependence between b_ptr line 64 and b_ptr line 65
remark #15346: vector dependence: assumed FLOW dependence between b_ptr line 65 and b_ptr line 64
remark #25018: Total number of lines prefetched=2
remark #25019: Number of spatial prefetches=2, dist=29
remark #25021: Number of initial-value prefetches=2
remark #25139: Using second-level distance 2 for prefetching spatial memory reference   [ test-mic.cpp(61,50) ]
remark #25015: Estimate of max trip count of loop=1048576
LOOP END

8

Решение

Это известная проблема — BKM должен использовать явные значения 0,1,2,3 для подсказок (t0, t1, t2, nta) в директивах / прагмах предварительной выборки (и НЕ использовать перечисление MM_HINT).

Это потому, что перечисление MM_HINT в файлах заголовка отображается по-разному:

/* constants to use with _mm_prefetch  (extracted from *mmintrin.h) */
#define _MM_HINT_T0 1
#define _MM_HINT_T1 2
#define _MM_HINT_T2 3
#define _MM_HINT_NTA    0    <--maps here
#define _MM_HINT_ENTA   4
#define _MM_HINT_ET0    5
#define _MM_HINT_ET1    6
#define _MM_HINT_ET2    7

Кроме того, заголовки Intel и gcc используют разные значения enum — это тоже хлопотно. Таким образом, подсказка —enums должна использоваться только для встроенных функций _mm_prefetch, а НЕ для директив prefetch.

Для этого примера вы должны использовать: #pragma prefetch a_ptr: 3

Тем не менее, этот предлагаемый синтаксис в настоящее время не может использоваться из-за дефекта, когда компилятор в настоящее время не может правильно соединить загрузочную память-ref a_ptr внутри цикла с выражением в директиве prefetch; поэтому временным решением является использование следующего синтаксиса:

#pragma prefetch *: 3

Заметка: Звездочка означает, что директива будет применяться к «ВСЕМ» ссылкам памяти внутри цикла. В этом цикле b_ptr не может быть предварительно выбран компилятором, так как он не является выражением линейного адреса. Так что «*» в любом случае применяется только к a_ptr — и приводит к vprefetchnta (как на KNC, так и на KNL).

Дефект будет исправлен в следующем выпуске.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]