Есть ли разделитель области по умолчанию в OpenMP?

Я новичок в OpenMP, только что сделал свою первую попытку, это было умножение матриц. Мне просто интересно, существует ли разделитель блоков по умолчанию в openMP? следующий мой код:

#include <stdio.h>
#include <omp.h>
#define MAX_THREADS 4
#define ASIZE 500

int main()
{
  /*intialization of 2 matrix*/     
  long matrixa [ASIZE][ASIZE];
  long matrixb [ASIZE][ASIZE];
  long matrixc [ASIZE][ASIZE] = {0};
  for(int i=0; i<ASIZE; i++)
    for(int j=0;j<ASIZE; j++)
    {
      matrixa [i][j] = 1;
      matrixb [i][j] = j;
    }

  omp_set_num_threads(MAX_THREADS);

  #pragma omp parallel
  {
    long cprivate [ASIZE][ASIZE] = {0};
    #pragma omp for
    for(int i =0 ;i<ASIZE; i++)
      for(int j=0; j<ASIZE; j++)
        for(int k=0; k<ASIZE; k++)
          cprivate[i][j]+=matrixa[i][k]*matrixb[k][j];

    #pragma omp critical
    for(int i =0 ;i<ASIZE; i++)
      for(int j=0; j<ASIZE; j++)
        matrixc[i][j]+=cprivate[i][j];

    //#pragma omp barrier
    if(omp_get_thread_num() ==0)
      for(int i=0; i<50; i++)
        printf("Snap of C array %lu \n", matrixc[1][i]); //print out chunk of the first row!

  }
}

Я думал, что таким образом, независимо от того, добавляю я #pragma omp barrier или нет, я могу получить ожидаемый результат, который должен быть результатом после полного выполнения блока #pragma omp critical.

вопросы

@ почему нет разницы с #pragma omp barrier или без #pragma omp barrier Есть идеи?

@ Я также заметил, что как только я увеличим размер массива до 600 сотен, он предупредит об ошибке сегментации при выполнении файла .o. Мое первоначальное предположение, что это был диапазон int (я изменил тип массива с int[] на long[] ), нет разницы.


person sthbuilder    schedule 11.02.2015    source источник
comment
Ваш вопрос немного сбивает с толку. Я отвечаю на ваши два вопроса в конце вашего вопроса. Тем не менее, ваш заголовок: Есть ли в OpenMP какой-либо разделитель области по умолчанию? Это другой вопрос. Что вы подразумеваете под разделителем области видимости?   -  person Z boson    schedule 12.02.2015


Ответы (1)


Ваш код, вероятно, не работает, потому что вы используете автоматическое хранилище. Вы должны использовать динамическое или статическое хранилище. Вот исправление вашего кода с использованием статического хранилища

#include <stdio.h>
#include <stdlib.h>
#define ASIZE 1000

long matrixa [ASIZE][ASIZE];
long matrixb [ASIZE][ASIZE];
long matrixc [ASIZE][ASIZE]; //set to zero by default with static storage

int main() {
    for(int i=0; i<ASIZE; i++) {
        for(int j=0;j<ASIZE; j++) {
            matrixa [i][j] = 1;
            matrixb [i][j] = j;
        }
    }

    #pragma omp parallel for
    for(int i=0 ;i<ASIZE; i++) {
        for(int j=0; j<ASIZE; j++) {
            long sum = 0;
            for(int k=0; k<ASIZE; k++) {
                sum += matrixa[i][k]*matrixb[k][j];
            }
            matrixc[i][j] = sum;
        }
    }
    for(int i=0; i<50; i++) printf("Snap of C array %lu \n", matrixc[1][i]);
}

Если вам нужен статически выделенный буфер для каждого потока, вам нужно использовать threadprivate, в противном случае используйте динамическое выделение.

Причина, по которой вам не нужно использовать барьер, заключается в том, что барьер является неявным с critical и многими другими конструкциями. Чтобы удалить неявный барьер, вы можете использовать nowait в некоторых случаях (например, #pragma omp parallel for nowait).

person Z boson    schedule 12.02.2015
comment
Не могли бы вы немного объяснить об автоматическом хранении? все глобальные переменные идут по этому пути по умолчанию? и когда вы говорите о статически выделенном буфере, вы имеете в виду матрицу cprivate, которую я использовал? Он называется статически выделенным из-за того, что я объявляю матрицу с размером матрицы напрямую? - person sthbuilder; 12.02.2015
comment
Автоматическое хранилище использует стек, который имеет ограниченный размер. В вашем коде matrixa, matrixb, matric, cprivate все выделяется из стека. Глобальные переменные и переменные, определенные с помощью ключевого слова static, используют статическое хранилище. - person Z boson; 12.02.2015
comment
cprivate не нужен, поэтому я его удалил. Однако, если вам действительно нужен частный буфер для каждого потока, вы должны использовать malloc для выделения с использованием кучи или threadprivate для статического хранилища для каждого потока. - person Z boson; 12.02.2015
comment
@javarookie, причина, по которой я использовал статическое распределение, заключается в том, что я должен использовать ту же запись. В противном случае с динамическим распределением вы должны сделать, например. matrixa[i*ASIZE+k]*matrixb[k*ASIZE+j]. - person Z boson; 12.02.2015