0

I have a very straightforward function that counts how many inner entries of an N by N 2D matrix (represented by a pointer arr) is below a certain threshold, and updates a counter below_threshold that is passed by reference:

void count(float *arr, const int N, const float threshold, int &below_threshold) {
    below_threshold = 0;  // make sure it is reset
    bool comparison;
    float temp;
    
    #pragma omp parallel for shared(arr, N, threshold) private(temp, comparison) reduction(+:below_threshold)
    for (int i = 1; i < N-1; i++)  // count only the inner N-2 rows
    {
        for (int j = 1; j < N-1; j++)  // count only the inner N-2 columns
        {
            temp = *(arr + i*N + j);
            comparison = (temp < threshold);
            below_threshold += comparison;
        }
    }
}

When I do not use OpenMP, it runs fine (thus, the allocation and initialization were done correctly already).

When I use OpenMP with an N that is less than around 40000, it runs fine.

However, once I start using a larger N with OpenMP, it keeps giving me a segmentation fault (I am currently testing with N = 50000 and would like to eventually get it up to ~100000).

Is there something wrong with this at a software level?


P.S. The allocation was done dynamically ( float *arr = new float [N*N] ), and here is the code used to randomly initialize the entire matrix, which didn't have any issues with OpenMP with large N:

void initialize(float *arr, const int N)
{
    #pragma omp parallel for
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            *(arr + i*N + j) = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        }
    }

}

UPDATE:

I have tried changing i, j, and N to long long int, and it still has not fixed my segmentation fault. If this was the issue, why has it already worked without OpenMP? It is only once I add #pragma omp ... that it fails.

7
  • FYI: How to generate random numbers in parallel?. Commented Mar 2, 2022 at 14:39
  • 1
    In good C++, please don't use new? Use std::vector or std:array instead. That might even have caught this error because may very well be allocating with a negative size. PS C++ also has a better random number generator than what you're using, which additionally can be used thread-safe. Commented Mar 2, 2022 at 14:56
  • @VictorEijkhout Is std::vector and std::array guaranteed to be memory contiguous? Commented Mar 2, 2022 at 15:14
  • Yes, contiguous, if you don't make a vector<vector<double>>. An array<array<double>> is going to be contiguous. I think. Commented Mar 2, 2022 at 15:18
  • Changing it to long int doesn't work... Commented Mar 2, 2022 at 16:44

1 Answer 1

3

I think, it is because, your value (50000*50000 = 2500000000) reached above INT_MAX (2147483647) in c++. As a result, the array access behaviour will be undefined.

So, you should use UINT_MAX or some other types that suits with your usecase.

Sign up to request clarification or add additional context in comments.

3 Comments

You should rather use long int or std::int64_t. unsigned will fail for N=100000, while a signed 64 bit integer will work.
std::ptrdiff_t is the type you are looking for. Signed (not all OpenMP implementations work with unsigned types in their loops), and not unnecessarily large on 32 bit systems. Also long int on Windows is 32 bit so that wouldn't work.
@paleonix This doesn't fix my segmentation fault...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.