Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7954 Discussions

Wrong answer with omp simd directive and c++ class

khsa1
Beginner
1,153 Views

Hi, I am tried to add the "#pragma omp simd" directive to a loop but get an incorrect answer. I have a simple reproducer below:

 

 

#include <iostream>

class Matrix {
public:
    double *data = nullptr;
    Matrix() {}
};


int main(int argc,char *argv[])
{
    int rows = 3, cols = 3;
    Matrix m;
    m.data = new double[rows*cols];

    for(int i = 0; i < rows*cols; i++) m.data[i] = 1.0;
#pragma omp simd collapse(2)
    for(int j = 0; j < cols; j++)
        for(int i = 0; i < rows; i++)
            m.data[j*cols+i] = 2.0;

    for(int i = 0; i < rows*cols; i++)
        std::cout << "m[" << i << "] = " << m.data[i] << std::endl;

    return 0;
}

 

Which I build with:

 

icpc -qopenmp reproducer.cpp

 

This gives the following output:

 

m[0] = 2
m[1] = 2
m[2] = 2
m[3] = 1
m[4] = 1
m[5] = 1
m[6] = 1
m[7] = 1
m[8] = 2

 

 

I found that if I remove the simd directive on line 17 or the constructor on line 6 then I get the expected result of 2 for all elements of m.

 

Does anyone have an idea of why I get incorrect results with my code? Am I doing something wrong or missing any necessary directives/declarations?

 

Thanks,
Sam

Labels (1)
0 Kudos
1 Solution
SantoshY_Intel
Moderator
1,101 Views

Hi,

 

Thanks for reaching out to us.

 

We were able to reproduce your issue on a Linux machine using the Intel classic C++ compiler(icpc) as shown in the below screenshot:

error.png

But, we can see from the below screenshots that it is working fine with the latest Intel oneAPI C++ compilers(icpx & dpcpp).

dpcpp.pngicpx.png

As it is working fine with Intel oneAPI C++ compilers, could you please try compiling with icpx or dpcpp compiler instead of Intel classic C++ compiler(icpc)?

 

Also, Intel Classic Compiler will enter "Legacy Product Support" mode, signaling the end of regular updates. Please refer to the article below for more details.

https://www.intel.com/content/www/us/en/developer/articles/technical/adoption-of-llvm-complete-icx.html

 

Thanks & Regards,

Santosh

 

View solution in original post

0 Kudos
5 Replies
SantoshY_Intel
Moderator
1,102 Views

Hi,

 

Thanks for reaching out to us.

 

We were able to reproduce your issue on a Linux machine using the Intel classic C++ compiler(icpc) as shown in the below screenshot:

error.png

But, we can see from the below screenshots that it is working fine with the latest Intel oneAPI C++ compilers(icpx & dpcpp).

dpcpp.pngicpx.png

As it is working fine with Intel oneAPI C++ compilers, could you please try compiling with icpx or dpcpp compiler instead of Intel classic C++ compiler(icpc)?

 

Also, Intel Classic Compiler will enter "Legacy Product Support" mode, signaling the end of regular updates. Please refer to the article below for more details.

https://www.intel.com/content/www/us/en/developer/articles/technical/adoption-of-llvm-complete-icx.html

 

Thanks & Regards,

Santosh

 

0 Kudos
khsa1
Beginner
1,069 Views

Thank you, that fixed that issue but I am still getting a wrong answer in my application code. I've narrowed down the problem to another issue for which I have created a reproducer.


There are 3 files:

1. main.cpp:

#include "helper.hpp"

#pragma omp declare simd
void increment_n_samefile(int *Count_N) {
    Count_N[0]++;
}

int main(int argc,char *argv[])
{
    int rows = 10, cols = 10;
    int Count_N[2] = {0};

#pragma omp simd collapse(2)
    for(int j = 0; j < cols; j++)
        for(int i = 0; i < rows; i++)
            increment_n_samefile(Count_N);

#pragma omp simd collapse(2)
    for(int j = 0; j < cols; j++)
        for(int i = 0; i < rows; i++)
            increment_n_otherfile(Count_N);


    printf("Count_N: {%d, %d}\n", Count_N[0], Count_N[1]);

    return 0;
}

2. helper.cpp:

#include "helper.hpp"

#pragma omp declare simd
void increment_n_otherfile(int *Count_N) {
    Count_N[1]++;
}

3. helper.hpp:

#include <omp.h>
#include <time.h>
#include <syslog.h>
#include <unistd.h>
#include <iostream>

#pragma omp declare simd
void increment_n_otherfile(int *Count_N);

I build with:

icpx -c -O2 --std=c++11 -qopenmp -g   main.cpp -o main.o
icpx -c -O2 --std=c++11 -qopenmp -g   helper.cpp -o helper.o
icpx -O2 --std=c++11 -qopenmp -g  -o miniapp.exe main.o helper.o

 which produces the following output:

Count_N: {100, 50}

I would expect 100 for both elements of the array, but the increment that is defined in a separate file is only incremented 50 times. Any idea why this is happening? Also, will this even work in a more complex code where the variable is incremented inside a conditional or should I expect race conditions when multiple iterations are executed at once in a vectorized code?

 

Thank you again for your help,

Sam

0 Kudos
SantoshY_Intel
Moderator
1,033 Views

Hi,

 

Thanks for providing the reproducer code samples and the steps to reproduce your issue.

 

We can expect race conditions when multiple iterations are executed at once in a vectorized code.

So, please use the "#pragma omp atomic" in your helper.cpp code as shown below:

#include "helper.hpp"
#pragma omp declare simd
void increment_n_otherfile(int *Count_N) {
#pragma omp atomic
    Count_N[1]++;
}

 

Now running the program using the icpx compiler gives you the correct output as shown in the below screenshot.

openmp.png

 

If this resolves your issue, make sure to accept this as a solution. This would help others with a similar issue.

 

Thanks & Regards,

Santosh

 

0 Kudos
khsa1
Beginner
1,022 Views

Thanks for you help.

-Sam

0 Kudos
SantoshY_Intel
Moderator
1,009 Views

Hi,


Thanks for accepting our solution. If you need any additional information, please post a new question as this thread will no longer be monitored by Intel.


Thanks & Regards,

Santosh




0 Kudos
Reply