<div dir="ltr">Hello everyone,<br><br>I'm having some data corruption issues when using the generic-elf plugin on the program below (blocked matrix multiplication). I tried to use 3 builds to test this program: the release branches "release/11.x" and "release/12.x", and the main branch as well. I observed the following behavior:<br><br>- release/11.x & main: the program works correctly with up to 4 OpenMP threads (OMP_NUM_THREADS=4), but with any number higher than that the result of the operation becomes incorrect. I believe that the problem may also happen with 2-4 threads, but with a lower likelihood to do so (of 500 executions, none have presented the problem);<br>- release/12.x: the program crashes due to a segfault inside a function called "__kmp_push_task" from OpenMP runtime regardless of the number of threads.<br><br>The program was compiled with the following command after setting the environment variables to point to the correct clang build:<br><br>"clang++ -fopenmp -fopenmp-targets=x86_64-pc-linux-gnu BlockMatMul.cpp"<br><br>Does anyone know if this is an already known problem (e.g. multiple parallel mappings happening at the same time)? What about the "__kmp_push_task"?<br><br>Thanks for the help,<br>Guilherme Valarini<br><br>Here is the program (sorry I could not come up with a smaller example to post it here). I have dumped the task graph build by OpenMP in a dot/graphviz form and it seems to be correct with the indented dependencies found at the function "BlockMatMul_TargetNowait":<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">#include <assert.h><br>#include <math.h><br>#include <stdio.h><br>#include <stdlib.h><br>#include <vector><br>#include <sys/time.h><br>#include <time.h><br>#include <unistd.h><br>class BlockMatrix {<br>private:<br>  const int rowsPerBlock;<br>  const int colsPerBlock;<br>  const long nRows;<br>  const long nCols;<br>  const int nBlocksPerRow;<br>  const int nBlocksPerCol;<br>  std::vector<std::vector<float *>> Blocks;<br>public:<br>  BlockMatrix(const int _rowsPerBlock, const int _colsPerBlock,<br>              const long _nRows, const long _nCols)<br>      : rowsPerBlock(_rowsPerBlock), colsPerBlock(_colsPerBlock), nRows(_nRows),<br>        nCols(_nCols), nBlocksPerRow(_nRows / _rowsPerBlock),<br>        nBlocksPerCol(_nCols / _colsPerBlock) {<br>    Blocks = std::vector<std::vector<float *>>(nBlocksPerCol);<br>    for (int i = 0; i < nBlocksPerCol; i++) {<br>      std::vector<float *> rowBlocks(nBlocksPerRow);<br>      for (int j = 0; j < nBlocksPerRow; j++) {<br>        rowBlocks[j] =<br>            (float *)calloc(_rowsPerBlock * _colsPerBlock, sizeof(float));<br>      }<br>      Blocks[i] = rowBlocks;<br>    }<br>  };<br>  ~BlockMatrix() {};<br>  // Initialize the BlockMatrix from 2D arrays<br>  void Initialize(float *matrix) {<br>    for (int i = 0; i < nBlocksPerCol; i++)<br>      for (int j = 0; j < nBlocksPerRow; j++) {<br>        float *CurrBlock = GetBlock(i, j);<br>        for (int ii = 0; ii < colsPerBlock; ++ii)<br>          for (int jj = 0; jj < rowsPerBlock; ++jj) {<br>            int curri = i * colsPerBlock + ii;<br>            int currj = j * rowsPerBlock + jj;<br>            CurrBlock[ii + jj * colsPerBlock] = matrix[curri + currj * nCols];<br>          }<br>      }<br>  }<br>  long Compare(float *matrix) {<br>    long fail=0;<br>    for (int i = 0; i < nBlocksPerCol; i++)<br>      for (int j = 0; j < nBlocksPerRow; j++) {<br>        float *CurrBlock = GetBlock(i, j);<br>        for (int ii = 0; ii < colsPerBlock; ++ii)<br>          for (int jj = 0; jj < rowsPerBlock; ++jj) {<br>            int curri = i * colsPerBlock + ii;<br>            int currj = j * rowsPerBlock + jj;<br>            float m_value = matrix[curri + currj * nCols];<br>            float bm_value = CurrBlock[ii + jj  * colsPerBlock];<br>            if(bm_value != m_value){<br>              fprintf(stdout, "i,j = %d,%d\n", i, j);<br>              fprintf(stdout, "BlockMAT[%d][%d] = %f\n", ii, jj, bm_value);<br>              fprintf(stdout, "MAT[%d][%d] = %f\n", curri, currj, m_value);<br>              fail++;<br>            }<br>          }<br>      }<br>    // Print results<br>    printf("Non-Matching Block Outputs: %ld\n", fail);<br>    return fail;<br>  }<br>  float *GetBlock(int i, int j) {<br>    assert(i < nBlocksPerCol && j < nBlocksPerRow && "Accessing outside block");<br>    return Blocks[i][j];<br>  }<br>};<br><br>#define BS 256<br>#define N 1024<br><br>// Initialize matrices.<br>void init(float *a, float *b) {<br>  int i, j;<br>  for (i = 0; i < N; ++i) {<br>    for (j = 0; j < N; ++j) {<br>      a[i * N + j] = (float)i + j % 100;<br>      b[i * N + j] = (float)i + j % 100;<br>    }<br>  }<br>}<br>int BlockMatMul_TargetNowait(BlockMatrix &A, BlockMatrix &B, BlockMatrix &C) {<br>  #pragma omp parallel<br>  #pragma omp master<br>  for (int i = 0; i < N / BS; ++i)<br>    for (int j = 0; j < N / BS; ++j) {<br>      float *BlockC = C.GetBlock(i, j);<br>      for (int k = 0; k < N / BS; ++k) {<br>        float *BlockA = A.GetBlock(i, k);<br>        float *BlockB = B.GetBlock(k,j);<br>        #pragma omp target depend(in: BlockA[0], BlockB[0]) \<br>                           depend(inout: BlockC[0]) \<br>                           map(to: BlockA[:BS*BS], BlockB[:BS*BS]) \<br>                           map(tofrom: BlockC[:BS*BS]) nowait<br>        #pragma omp parallel for<br>        for(int ii = 0; ii < BS; ii++)<br>          for(int jj = 0; jj < BS; jj++) {<br>            for(int kk = 0; kk < BS; ++kk)<br>              BlockC[ii + jj * BS] += BlockA[ii + kk * BS] * BlockB[kk + jj * BS];<br>          }<br>      }<br>    }<br>  return 0;<br>}<br>void Matmul(float *a, float *b, float *c) {<br>  for (int i = 0; i < N; ++i) {<br>    for (int j = 0; j < N; ++j) {<br>      float sum = 0.0;<br>      for (int k = 0; k < N; ++k) {<br>        sum = sum + a[i * N + k] * b[k * N + j];<br>      }<br>      c[i * N + j] = sum;<br>    }<br>  }<br>}<br>int main(int argc, char *argv[]) {<br>  double t_start, t_end;<br>  int ret = 0;<br>  float *a = (float *)malloc(sizeof(float) * N * N);<br>  float *b = (float *)malloc(sizeof(float) * N * N);<br>  float *c = (float *)calloc(sizeof(float), N * N);<br>  init(a, b);<br>  auto BlockedA = BlockMatrix(BS, BS, N, N);<br>  BlockedA.Initialize(a);<br>  BlockedA.Compare(a);<br>  auto BlockedB = BlockMatrix(BS, BS, N, N);<br>  BlockedB.Initialize(b);<br>  BlockedB.Compare(b);<br>  Matmul(a, b, c);<br>  auto BlockedC = BlockMatrix(BS, BS, N, N);<br>  BlockMatMul_TargetNowait(BlockedA, BlockedB, BlockedC);<br>  if(BlockedC.Compare(c) > 0) {<br>    // exit code to error if there is any missmatch<br>    ret = 1;<br>  }<br>  free(a);<br>  free(b);<br>  free(c);<br>  return ret;<br>}</blockquote></div>