Nvc++ -O2: Segfault for *= in large std::complex<double> array

Hello everyone,

if I compile the following code with nvc++ segfaulttest.cpp -O2 -o segfaulttest and execute it, it first prints the address of the pointer (as expected) and then gives a segmentation fault.

#include <complex>
#include <iostream>

int main(){
    int size = 150000000;

    auto pointer = (std::complex<double> *) malloc(size * sizeof(std::complex<double>));

    // Make sure that allocation worked
    if (pointer)
    {
        std::cout << pointer << std::endl;
    }

    for (int ind =0; ind < size; ++ind)
    {
        pointer[ind] *= 5.;
    }
    
    free(pointer);
    return 0;
}

Any of the following actions resolves the issue:

  • change nvc++ to g++
  • reduce the optimization level to -O0 or -O1 (the problem occurs at -O2 and -O3)
  • reduce the parameter size to less than about 130 million
  • print the index every now and then, e.g. by adding if (ind % 1000000 == 0) std::cout << ind << std::endl; to the for loop
  • write out the *=operator as pointer[ind] = pointer[ind] * 5.;, this was particularly surprising for me.

I tried it out on an Ubuntu 22.04 with HPC SDK version 22.9 and on a WSL2 Ubuntu 20.04 with HPC SDK version 22.5. Both show the same behavior.

Kind regards,
Simon

Hi Simon,

It looks like the array is right at the 2GB boundary so will need 64-bit offsets. Hence try changing the “ind” variable to be a long instead of an int so the compiler knows to use 64-bits. You may also want to use the “-mcmodel=medium” flag if you go bigger.

While I’m not 100% sure why the segv doesn’t occur at lower opts, but my guess is that we’re doing more alignment. A segv won’t occur until after crossing a page boundary, so the alignment may be changing how the pages are used.

-Mat

Hi Mat, thank you very much for your reply! That solved the issue.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.