Главная страница
Навигация по странице:

  • Другие функции Имя функции

  • Команды для инициализации и работы с памятью Инициализация памяти

  • Инициализация значений Имя функции

  • Операции записи Имя функции

  • Поддержка кэш-памяти в SSE

  • 3. Использование встроенных функций SSE в программе на языке Си

  • 7 мая 2011 года . Варианты.

  • Лабораторная работа № 4 Программирование многоядерных архитектур

  • Методические указания.

  • 2. Примеры программ с использованием OpenMP 2.1. Определение и печать номера потока

  • 2.2. Распределение работы

  • 2.3. Использование секций

  • 2.4. Параллельная реализация одиночных циклов

  • 2.5. Критические секции

  • 2.6. Редуцируемые операции

  • 20 мая 2011 года . Крайний срок защиты – 25 мая 2011 года . Варианты.

  • лабы архитект. Методические указания к лабораторным работам для студентов 1го курса фпми


    Скачать 417 Kb.
    НазваниеМетодические указания к лабораторным работам для студентов 1го курса фпми
    Анкорлабы архитект
    Дата02.11.2020
    Размер417 Kb.
    Формат файлаdoc
    Имя файлаArchLabs.doc
    ТипМетодические указания
    #147348
    страница3 из 3
    1   2   3

    Операции преобразования типов

    Имя функции

    Операция

    Инструкция

    _mm_cvtss_si32

    Преобразует младший float в 32-битное целое

    CVTSS2SI

    _mm_cvtps_pi32

    Преобразует два младших float в два упакованных 32-битных целых

    CVTPS2PI

    _mm_cvttss_si32

    Преобразует младший float в 32-битное целое, отбрасывая дробную часть

    CVTTSS2SI

    _mm_cvttps_pi32

    Преобразует два младших float в два упакованных 32-битных целых, отбрасывая дробную часть

    CVTTPS2PI

    _mm_cvtsi32_ss

    Преобразует 32-битное целое в float

    CVTSI2SS

    _mm_cvtpi32_ps

    Преобразует два упакованных 32-битных целых в два младших float

    CVTTPS2PI

    _mm_cvtpi16_ps

    Преобразует четыре упакованных 16-битных целых в упакованные float

    составная

    _mm_cvtpu16_ps

    Преобразует четыре упакованных беззнаковых 16-битных целых в упакованные float

    составная

    _mm_cvtpi8_ps

    Преобразует четыре младших упакованных 8-битных целых в четыре упакованных float

    составная

    _mm_cvtpu8_ps

    Преобразует четыре младших упакованных беззнаковых 8-битных целых в четыре упакованных float

    составная

    _mm_cvtpi32x2_ps

    Преобразует две пары упакованных 32-битных целых в четыре упакованных float

    составная

    _mm_cvtps_pi16

    Преобразует четыре упакованных float в четыре 16-битных целых

    составная

    _mm_cvtps_pi8

    Преобразует четыре упакованных float в четыре младших 8-битных целых

    составная

    Другие функции

    Имя функции

    Операция

    Инструкция

    _mm_shuffle_ps

    перестановка упакованных значений

    SHUFPS

    _mm_shuffle_pi16

    перестановка упакованных значений

    PSHUFW

    _mm_unpackhi_ps

    выборка старших значений

    UNPCKHPS

    _mm_unpacklo_ps

    выборка младших значений

    UNPCKLPS

    _mm_loadh_pi

    загрузка старших значений

    MOVHPS reg, mem

    _mm_storeh_pi

    сохранение старших значений

    MOVHPS mem, reg

    _mm_movehl_ps

    копирование старшей половины в младшую

    MOVHLPS

    _mm_movelh_ps

    копирование младшей половины в старшую

    MOVLHPS

    _mm_loadl_pi

    загрузка младших значений

    MOVLPS reg, mem

    _mm_storel_pi

    сохранение младших значений

    MOVLPS mem, reg

    _mm_movemask_ps

    создание знаковой маски

    MOVMSKPS

    _mm_getcsr

    сохранить регистр состояния

    STMXCSR

    _mm_setcsr

    установить регистр состояния

    LDMXCSR

    Команды для инициализации и работы с памятью

    Инициализация памяти

    Имя функции

    Операция

    Инструкция

    _mm_load_ss

    загрузить младшее значение и очистить остальные три значения

    MOVSS

    _mm_load1_ps

    загрузить одно значение во все четыре позиции

    MOVSS + Shuffling

    _mm_load_ps

    Загрузить четыре значения по выровненному адресу

    MOVAPS

    _mm_loadu_ps

    Загрузить четыре значения по невыровненному адресу

    MOVUPS

    _mm_loadr_ps

    Загрузить четыре значения в обратном порядке

    MOVAPS + Shuffling



    Инициализация значений

    Имя функции

    Операция

    Инструкция

    _mm_set_ss

    устанавливает самое младшее значение и обнуляет три остальных

    составная

    _mm_set1_ps

    устанавливает четыре позиции в одно значение

    составная

    _mm_set_ps

    устанавливает четыре значения, выровненные по адресу

    составная

    _mm_setr_ps

    устанавливает четыре значения в обратном порядке

    составная

    _mm_setzero_ps

    Обнуляет все четыре значения

    составная



    Операции записи

    Имя функции

    Операция

    Инструкция

    _mm_store_ss

    записать младшее значение

    MOVSS

    _mm_store1_ps

    записать младшее значение во все четыре позиции

    MOVSS + Shuffling

    _mm_store_ps

    записать четыре значения по выровненному адресу

    MOVAPS

    _mm_storeu_ps

    записать четыре значения по невыровненному адресу

    MOVUPS

    _mm_storer_ps

    записать четыре значения в обратном порядке

    MOVAPS + Shuffling

    _mm_move_ss

    записать младшее значение и оставить без изменения три остальных значения

    MOVSS

    Поддержка кэш-памяти в SSE

    Имя функции

    Операция

    Инструкция

    _mm_prefetch

    Загружает одну кэш-строку по указанному адресу в кэш-память

    PREFETCH

    _mm_stream_pi

    Записывает данные в память без записи в кэш

    MOVNTQ

    _mm_stream_ps

    Записывает данные в память без записи в кэш по адресу, выровненному по 16 байт

    MOVNTPS

    _mm_sfence

    Гарантирует, что все предшествующие записи в память завершатся до следующей записи.

    SFENCE

    3. Использование встроенных функций SSE в программе на языке Си

    // скалярное произведение векторов

    #include

    #include

    #define N 10000000

    // «обычная» функция

    float inner1(float *x,float *y,int n)

    {

    float s;

    int i;

    s=0;

    for(i=0;i
    s+=x[i]*y[i];

    return s;

    }

    // функция с использованием SSE intrinsics

    float inner2(float *x,float *y,int n)

    {

    float sum;

    int i;

    __m128 *xx,*yy;

    __m128 p,s;

    xx=(__m128 *)x;

    yy=(__m128 *)y;

    s=_mm_set_ps1(0);

    for (i=0;i
    {

    p=_mm_mul_ps(xx[i], yy[i]); // векторное умножение четырех чисел

    s=_mm_add_ps(s,p); // векторное сложение четырех чисел

    }

    p=_mm_movehl_ps(p,s); // перемещение двух старших значений s в младшие p

    s=_mm_add_ps(s,p); // векторное сложение

    p=_mm_shuffle_ps(s,s,1);//перемещение второго значения в s в младшую позицию в p

    s=_mm_add_ss(s,p); // скалярное сложение

    _mm_store_ss(&sum,s); // запись младшего значения в память

    return sum;

    }

    int main()

    {

    float *x,*y, s;

    long t;

    int i;

    // выделение памяти с выравниванием

    x=(float *)_mm_malloc(N*sizeof(float),16);

    y=(float *)_mm_malloc(N*sizeof(float),16);

    for (i=0;i
    {

    x[i]=10*i/N;

    y[i]=10*(N-i-1)/N;

    }

    // Using x87

    s=inner1(x,y,N);

    printf("Result: %f\n",s);

    // Using SSE

    s=inner2(x,y,N);

    printf("Result: %f\n",s);

    _mm_free(x);

    _mm_free(y);

    return 0;

    }

    Задание.

    1. Реализовать процедуру умножения квадратных матриц (размером кратным четырём) без использования специальных расширений и с использованием расширений SSE, сравнить время выполнения этих реализаций (Обязательное задание – 10 баллов).

    2. В соответствии с вариантом задания реализовать матрично-векторную (с одинаковым размером матриц и векторов кратным четырём) процедуру с использованием расширений SSE (Дополнительное задание – 7 баллов).

    3. С использованием инструкции cpuid определить наличие расширения SSE (Дополнительное задание – 3 балла).

    4. Крайний срок сдачи – 7 мая 2011 года.

    Варианты.

    В предложенных вариантах предполагается, что – скаляры, – векторы, – матрицы:

    1. Операция .

    2. Операция .

    3. Операция .

    4. Операция .

    5. Операция .

    6. Операция .

    7. Операция .

    8. Операция .

    9. Операция .

    10. Операция .

    Лабораторная работа № 4

    Программирование многоядерных архитектур

    Цель работы. Использование интерфейса OpenMP для программирования простых многопоточных приложений.

    Методические указания.

    1. Интерфейс OpenMP

    OpenMP – интерфейс прикладного программирования (API) для масштабируемых SMP-систем (симметричные мультипроцессорные системы) в модели общей памяти.

    Исполняемый процесс в памяти может состоять из множественных нитей, которые имеют общее адресное пространство, но разные потоки команд и раздельные стэки. В простейшем случае, процесс состоит из одной нити, выполняющую функцию main. Нити иногда называют также потоками, легковесными процессами, LWP (light-weight processes). OpenMP основан на существовании множественных потоков в общедоступной памяти [3]. Схема процесса представлена на рисунке.



    Рисунок 8.

    Все программы OpenMP начинаются как единственный процесс с главным потоком. Главный поток выполняется последовательно, пока не сталкиваются с первой областью параллельной конструкции. Создание нескольких потоков (FORK) и объединение (JOIN) проиллюстрировано на рисунке.



    Рисунок 9.

    2. Примеры программ с использованием OpenMP

    2.1. Определение и печать номера потока

    #include

    #include

    void main ()

    {

    int nthreads, tid;

    /* Fork a team of threads giving them their own copies of variables */

    #pragma omp parallel private(tid)

    {

    /* Obtain and print thread id */

    tid = omp_get_thread_num();

    printf("Hello World from thread = %d\n", tid);

    /* Only master thread does this */

    if (tid == 0)

    {

    nthreads = omp_get_num_threads();

    printf("Number of threads = %d\n", nthreads);

    }

    } /* All threads join master thread and terminate */

    }

    2.2. Распределение работы

    #include

    #include

    #define CHUNKSIZE 100

    #define N 1000

    void main ()

    {

    int i, chunk;

    float a[N], b[N], c[N];

    /* Some initializations */

    for (i=0; i < N; i++)

    a[i] = b[i] = i * 1.0;

    chunk = CHUNKSIZE;

    #pragma omp parallel shared(a,b,c,chunk) private(i)

    {

    #pragma omp for schedule(dynamic,chunk) nowait

    for (i=0; i < N; i++)

    c[i] = a[i] + b[i];

    } /* end of parallel section */

    }

    2.3. Использование секций

    #include

    #include

    #define N 1000

    void main ()

    {

    int i;

    float a[N], b[N], c[N], d[N];

    /* Some initializations */

    for (i=0; i < N; i++)

    {

    a[i] = i * 1.5;

    b[i] = i + 22.35;

    }

    #pragma omp parallel shared(a,b,c,d) private(i)

    {

    #pragma omp sections nowait

    {

    #pragma omp section

    for (i=0; i < N; i++)

    c[i] = a[i] + b[i];

    #pragma omp section

    for (i=0; i < N; i++)

    d[i] = a[i] * b[i];

    } /* end of sections */

    } /* end of parallel section */

    }

    2.4. Параллельная реализация одиночных циклов

    #include

    #include

    #define N 1000

    #define CHUNKSIZE 100

    void main ()

    {

    int i, chunk;

    float a[N], b[N], c[N];

    /* Some initializations */

    for (i=0; i < N; i++)

    a[i] = b[i] = i * 1.0;

    chunk = CHUNKSIZE;

    #pragma omp parallel for shared(a,b,c,chunk) private(i) schedule(static,chunk)

    for (i=0; i < n; i++)

    c[i] = a[i] + b[i];

    }

    2.5. Критические секции

    #include

    void main()

    {

    int x;

    x = 0;

    #pragma omp parallel shared(x)

    {

    #pragma omp critical

    x = x + 1;

    } /* end of parallel section */

    }

    2.6. Редуцируемые операции

    #include

    #include

    void main ()

    {

    int i, n, chunk;

    float a[100], b[100], result;

    /* Some initializations */

    n = 100;

    chunk = 10;

    result = 0.0;

    for (i=0; i < n; i++)

    {

    a[i] = i * 1.0;

    b[i] = i * 2.0;

    }

    #pragma omp parallel for default(shared) private(i) schedule(static,chunk) \ reduction(+:result)

    for (i=0; i < n; i++)

    result = result + (a[i] * b[i]);

    printf("Final result= %f\n",result);

    }

    Задание.

    1. В соответствии с вариантом задания реализовать алгоритм с использованием интерфейса OpenMP (Дополнительное задание: варианты 1,2 и 3 – 20 баллов, вариант 4 – 30 баллов).

    2. Защита лабораторной работы (Дополнительное задание – 10 баллов).

    3. Крайний срок сдачи – 20 мая 2011 года.

    4. Крайний срок защиты – 25 мая 2011 года.

    Варианты.

    1. Скалярное произведение двух векторов.

    2. Умножение матрицы на вектор.

    3. Умножение матрицы на матрицу.

    4. Решение системы линейных алгебраических уравнений методом Гаусса.

    Литература

    1. Спецификация инструкции cpuid для процессоров Intel http://www.intel.com/Assets/PDF/appnote/241618.pdf

    2. Спецификация инструкции cpuid для процессоров AMD http://support.amd.com/us/Embedded_TechDocs/25481.pdf

    3. Корнеев В.Д. Параллельное программирование кластеров // Новосибирск. НГТУ. 2008. – 312 с.
    1   2   3


    написать администратору сайта