Требуемое время для выгрузки функции в Intel Xeon Phi

Существует ли заранее определенное время, необходимое для вызова разгрузки для передачи данных (параметров) функции с хоста на Intel MIC(сопроцессор Xeon Phi серии 3120)?

В частности, я выполняю вызов разгрузки ("#pragma offload target(mic)") для функции, которую я хочу выполнить на MIC. Функция имеет 15 параметров (указатели и переменные), и я уже подтвердил правильность передачи параметров в MIC. Однако я упростил код с целью проверки времени передачи параметров, и поэтому он содержит только одну простую функцию "printf()". Я использую заголовочный файл "gettimeofday()" из "sys/time.h" для измерения времени, как это показано в приведенном ниже коде:

Некоторые сведения об оборудовании для хоста: Процессор Intel® Core ™ TM i7-3770 @ 3,40 ГГц / CentOS выпуск 6,8 / PCI Express Revision 2.0

main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>

__attribute__ (( target (mic))) unsigned long long ForSolution = 0;
__attribute__ (( target (mic))) unsigned long long sufficientSol = 1;
__attribute__ (( target (mic))) float timer = 0.0;

__attribute__ (( target (mic))) void function(float *grid, float *displ, unsigned long long *li, unsigned long long *repet, float *solution, unsigned long long dim, unsigned long long numOfa, unsigned long long numLoops, unsigned long long numBlock, unsigned long long thread, unsigned long long blockGrid, unsigned long long station, unsigned long long bytesSol, unsigned long long totalSol, volatile unsigned long long *prog);

   float    *grid, *displ, *solution;
   unsigned long long   *li,repet;
   volatile unsigned long long  *prog;
   unsigned long long dim = 10, grid_a = 3, numLoops = 2, numBlock = 0;
   unsigned long long thread = 220, blockGrid = 0, station = 12;
   unsigned long long station_at = 8, bytesSol, totalSol;

   bytesSol = dim*sizeof(float);
   totalSol = ((1024 * 1024 * 1024) / bytesSol) * bytesSol;



   /******** Some memcpy() functions here for the pointers*********/                   



gettimeofday(&start, NULL);

   #pragma offload target(mic) \
        in(grid:length(dim * grid_a * sizeof(float))) \
        in(displ:length(station * station_at * sizeof(float))) \
        in(li:length(dim * sizeof(unsigned long long))) \
        in(repet:length(dim * sizeof(unsigned long long))) \
        out(solution:length(totalSol/sizeof(float))) \
        in(dim,grid_a,numLoops,numBlock,thread,blockGrid,station,bytesSol,totalSol) \
        in(prog:length(sizeof(volatile unsigned long long))) \
        inout(ForSolution,sufficientSol,timer)
   {
        function(grid, displ, li, repet, solution, dim, grid_a, numLoops, numBlock, thread, blockGrid, station, bytesSol, totalSol, prog);
   }

    gettimeofday(&end, NULL);  

    printf("Time to tranfer data on Intel Xeon Phi: %f sec\n", (((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0) - timer);
    printf("Time for calculations: %f sec\n", timer);

function.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <omp.h>

void function(float *grid, float *displ, unsigned long long *li, unsigned long long *repet, float *solution, unsigned long long dim, unsigned long long numOfa, unsigned long long numLoops, unsigned long long numBlock, unsigned long long thread, unsigned long long blockGrid, unsigned long long station, unsigned long long bytesSol, unsigned long long totalSol, volatile unsigned long long *prog)
{
    struct timeval      timer_start, timer_end;

    gettimeofday(&timer_start, NULL);

printf("Hello World!!!\n");


    gettimeofday(&timer_end, NULL);

    timer = ((timer_end.tv_sec - timer_start.tv_sec) * 1000000.0 + (timer_end.tv_usec - timer_start.tv_usec)) / 1000000.0 ;  
}

Результаты терминала:

Time to tranfer data on Intel Xeon Phi: 3.512706 sec
Time for calculations: 0.000002 sec
Hello World!!!

Коду требуется 3,5 секунды для завершения "цели разгрузки". Является ли приведенный выше результат нормальным? Есть ли способ уменьшить эту значительную задержку вызова разгрузки?

1 ответ

Решение

Давайте посмотрим на шаги здесь:

а) для самого первого #pragma offload MIC инициализируется; что, вероятно, включает в себя его сброс, загрузку урезанного Linux (и ожидание, пока он запустит все процессоры, инициализирует управление памятью, запустит драйвер psuedo-NIC и т. д.) и загрузит ваш код на устройство. Это, вероятно, занимает несколько секунд в одиночку.

б) Все входные данные загружаются в MIC.

в) Функция выполнена.

г) Все выходные данные загружаются из MIC.

Для передачи необработанных данных через PCI Express Revision 2.0 (x16) макс. пропускная способность - 8 ГБ / с; однако вы не получите макс. пропускная способность. Из того, что я помню, связь с Phi включает в себя общие кольцевые буферы и IRQ "дверного звонка" с драйверами "псевдо NIC" с обеих сторон (на хосте и на ОС сопроцессора); и со всеми рукопожатиями и накладными расходами я был бы удивлен, если бы вы получили половину максимума. пропускная способность.

Я думаю, что общий объем загруженного кода, загруженных данных и загруженных данных превышает 1 ГБ (например, out(solution:length(totalSol/sizeof(float))) 1 ГиБ сам по себе). Если мы предполагаем "около 4 ГиБ / с", это как минимум еще ~250 мс.

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

Другие вопросы по тегам