Я делаю некоторые тесты производительности на Xeon Phi с использованием Cilk Plus с разгрузкой.
В простой программе векторного добавления у меня есть 2 способа сделать это:
использование cilk_for для разделения задач на разные потоки в Xeon phi:
__declspec(target(mic)) void vector_add(double *A,double *B,double *C,
int vector_size)
{
_Cilk_for(int i=0;i<vector_size;i++)
{
C[i] += A[i] + B[i];
}
}
double *A,*B,*C;
//allocating and initializing A, B ,C using malloc.....
#pragma offload target(mic:0) \
in(B:length(vector_size)) \
in(A:length(vector_size)) \
in(C:length(vector_size)) \
in(vector_size )
{
vector_add(A,B,C,vector_size);
}
Используя векторную аннотацию:
double *A,*B,*C;
//allocating and initializing A, B ,C using malloc.....
#pragma offload target(mic:0) \
in(B:length(vector_size)) \
in(A:length(vector_size)) \
in(C:length(vector_size))
//in(vector_size )
//signal(offload0)
{
C[0:vector_size] = A[0:vector_size]+B[0:vector_size];
}
Мой тест показывает, что первый способ в ~ 10 раз быстрее, чем второй на xeon phi. Та же самая история происходит, когда я не разгружаю и запускаю его на хост-процессоре Xeon E5.
Сначала я хочу знать, правильно ли мое понимание:
Первый способ использует только параллелизм потоков (60 ядер * по 4 потока в каждом) в XEON phi. Но никакая векторная операция не будет выполнена.
Второй способ использует векторизацию только потому, что этот код будет выполняться только в одном потоке с использованием инструкций SIMD (IMCI).
Во-вторых, я хотел бы знать, как правильно написать это так, чтобы он одновременно разделял задачи на разные потоки и использовал векторные инструкции на Xeon phi?
Заранее спасибо.
На самом деле, если вы посмотрите на отчеты по оптимизации, которые создает компилятор (-opt-report), или на вывод VTune, если он у вас есть, вы можете быть удивлены. Ваш второй пример, как вы и предполагали, только векторизован. Тем не менее, ваш первый пример также может векторизовать в дополнение к распараллеливанию. Помните, что _Cilk_for не раздает отдельные итерации, а порции итераций, которые в некоторых случаях могут быть векторизованы.
Для лучшего контроля вы можете попробовать поэкспериментировать с вложенными циклами, чтобы явно разделить параллельные и векторные циклы, или поиграться с размером зерна, чтобы изменить объем работы, над которой должен работать поток в любой момент времени, или несколько разных прагм.
Для совета по оптимизации специально для сопроцессора Intel Xeon Phi, я хотел бы указать людям на https://software.intel.com/en-us/articles/programming-and-compiling-for-intel-many-integrated-core-architecture, но я думаю, что вы могли бы найти что-то слишком простое Тем не менее, если вы хотите копаться в ….