Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++ & OpenMP

57 views
Skip to first unread message

Bob

unread,
Nov 29, 2017, 9:12:48 PM11/29/17
to
Not a homework problem, too dumb for school.
https://forum.level1techs.com/t/c-openmp/121868

Öö Tiib

unread,
Nov 30, 2017, 2:00:46 AM11/30/17
to
On Thursday, 30 November 2017 04:12:48 UTC+2, Bob wrote:
> Not a homework problem, too dumb for school.
> https://forum.level1techs.com/t/c-openmp/121868

It hangs or crashes or what means "dies" and where?
Can't you run it in debugger?

Necron_99

unread,
Nov 30, 2017, 10:07:07 AM11/30/17
to
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote in news:1a39d558-c400-4cad-bdfc-
34d829...@googlegroups.com:
I've run smaller values of n in valgrind, no leaks detected. It dies during execution of the openp for
section. Anyway I'm following up on some suggestions I got over at
https://forum.level1techs.com/t/c-openmp/121868

Öö Tiib

unread,
Nov 30, 2017, 12:24:52 PM11/30/17
to
Still no answer what means "dies"? Programs are not alive so can't die.

Christian Gollwitzer

unread,
Nov 30, 2017, 5:59:54 PM11/30/17
to
Am 30.11.2017 um 03:12 schrieb Bob:
> Not a homework problem, too dumb for school.
> https://forum.level1techs.com/t/c-openmp/121868

You manipulate "x" (is this a global std::vector?) inside of
randomSample(). This is called in your openMP-loop and will therefore
execute in parallel. This can't work. You need to make sure that the
same object is not touched simultaneously from multiple threads. Either
protect with locks (lock_guard<>), or duplicate the vector. And even
better, remove the global. It is not sure where it is coming from, since
you don't show complete compilable code.

Christian

Öö Tiib

unread,
Nov 30, 2017, 6:27:44 PM11/30/17
to
On Friday, 1 December 2017 00:59:54 UTC+2, Christian Gollwitzer wrote:
> Am 30.11.2017 um 03:12 schrieb Bob:
> > Not a homework problem, too dumb for school.
> > https://forum.level1techs.com/t/c-openmp/121868
>
> You manipulate "x" (is this a global std::vector?) inside of

To me x seems to be protected std::vector<float> member of Stats
that is virtual base class of Sample whose instance the sample likely
is.
The '#pragma omp parallel for private(sample)' does separate copy
of that sample for each iteration. It can be that those copies
somehow fragment memory and cause the problems.

> randomSample(). This is called in your openMP-loop and will therefore
> execute in parallel. This can't work. You need to make sure that the
> same object is not touched simultaneously from multiple threads. Either
> protect with locks (lock_guard<>), or duplicate the vector. And even
> better, remove the global. It is not sure where it is coming from, since
> you don't show complete compilable code.

Yes. My comments above can be wrong because we haven't seen any actual
program code, just what may be fragments of it and reports that the
program "dies".

Riccardo Zanella

unread,
Nov 30, 2017, 7:13:59 PM11/30/17
to
Il 30/11/17 03:12, Bob ha scritto:
> Not a homework problem, too dumb for school.
> https://forum.level1techs.com/t/c-openmp/121868
>

I got no problem up to 30k, too tired to try more :)
Then I changed to c++11 and random generators, please check whether the
generation fits your needs.

Compile with:
g++-6 -std=c++11 -fopenmp -O2 -march=native main.cpp stats.cpp -lgomp

Remember to set something, for Bash you can use:
export OMP_NUM_THREADS=2
export OMP_SCHEDULE=static,1

Riccardo

===== main.cpp =============
#include <vector>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <cstdlib>
#include <omp.h>

#include "stats.hpp"

int main( int argc, char *argv[]) {
try {
int n = 50;
if (argc == 2)
if( (std::istringstream(argv[1]) >> n).fail() || (n < 1) )
throw std::runtime_error("bad input");

std::cerr << "Up to " << n << std::endl;
std::vector< float > x (n);
Sample sample;
std::vector< std::vector<float> > table(n-1);
for ( int ii = 0; ii < n-1; ++ii )
table[ii] = std::vector< float >(8);

double start = omp_get_wtime();

# pragma omp parallel for private(sample) schedule(runtime)
for( int ii = 2; ii < n+1; ++ii ){
if ( (ii % 1000 == 0) )
std::cerr << ".";
sample.randomSample(x, ii);
table[ii-2][0] = sample.computeMean();
table[ii-2][1] = sample.computeMedian();
table[ii-2][2] = sample.computeVar();
table[ii-2][3] = sample.computeStd();
table[ii-2][4] = sample.computeMeanDev();
table[ii-2][5] = sample.computeMedianDev();
table[ii-2][6] = sample.computeSkewness();
table[ii-2][7] = sample.computeMedianSkew();
}
double end = omp_get_wtime();
std::cout << std::endl
<< "Time: " << end -start << "[s]" << std::endl;
}
catch ( std::exception &e ){
std::cerr << e.what() << std::endl;
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}


===== stats.cpp (excerpt) =============
#include <random>

void Sample::randomSample(const std::vector<float>& pop, int m)
{
if (m <= 0) {
n = 0;
return;
}
n = m;
int pop_size = pop.size();
// use an index vector - preserve passed vector
std::vector<int> idx(pop_size); // <--------------------------
for (int i = 0; i < pop_size; i++) idx.push_back(i);
// perform pop_size random swaps
std::default_random_engine eng{ static_cast< long unsigned int >
(time(0))};
std::uniform_int_distribution<int> gen( 0, pop_size-1 );
for (int i = 0; i < pop_size; i++) {
// int rndidx = (int)(pop_size*((float)rand()/(float)IMAX));
int rndidx = gen(eng);
int tmp = idx[i];
idx[i] = idx[rndidx];
idx[rndidx] = tmp;
}
// x.clear(); // clear in case something is there
x.resize(n); // <------------------
for (int i = 0; i < n; i++) // x.push_back(pop[idx[i]]);
x[i] = pop[idx[i]]; // <------------------
}

Alain Ketterlin

unread,
Dec 1, 2017, 6:45:29 AM12/1/17
to
Öö Tiib <oot...@hot.ee> writes:

> On Friday, 1 December 2017 00:59:54 UTC+2, Christian Gollwitzer wrote:
>> Am 30.11.2017 um 03:12 schrieb Bob:
>> > Not a homework problem, too dumb for school.
>> > https://forum.level1techs.com/t/c-openmp/121868
>>
>> You manipulate "x" (is this a global std::vector?) inside of
>
> To me x seems to be protected std::vector<float> member of Stats
> that is virtual base class of Sample whose instance the sample likely
> is.
> The '#pragma omp parallel for private(sample)' does separate copy
> of that sample for each iteration. It can be that those copies
> somehow fragment memory and cause the problems.

The OpenMP spec describes private (in the case of C++), in Section
2.15.3.3, as:

| The new list item is initialized, or has an undefined initial value, as
| if it had been locally declared without an initializer.

"List item" here is an item in the private clause. The "new" list item
is the one allocated for each thread.

And later:

| A variable of class type (or array thereof) that appears in a private
| clause requires an accessible, unambiguous default constructor for the
| class type.

>> randomSample(). This is called in your openMP-loop and will therefore
>> execute in parallel. This can't work. You need to make sure that the
>> same object is not touched simultaneously from multiple threads. Either
>> protect with locks (lock_guard<>), or duplicate the vector. And even
>> better, remove the global. It is not sure where it is coming from, since
>> you don't show complete compilable code.
>
> Yes. My comments above can be wrong because we haven't seen any actual
> program code, just what may be fragments of it and reports that the
> program "dies".

Right, the code does not show the relevant parts. Probably
race-conditions on data referenced inside sample (and copies thereof).

-- Alain.

Necron_99

unread,
Dec 1, 2017, 12:23:21 PM12/1/17
to
Thank you, this was the branch of the thread that proved to be most relevant.

Alain Ketterlin <al...@universite-de-strasbourg.fr.invalid> wrote in
news:87y3mml...@universite-de-strasbourg.fr.invalid:

> Öö Tiib <oot...@hot.ee> writes:
>
>> On Friday, 1 December 2017 00:59:54 UTC+2, Christian Gollwitzer
>> is.
>> The '#pragma omp parallel for private(sample)' does separate copy
>> of that sample for each iteration. It can be that those copies
>> somehow fragment memory and cause the problems.
>
> The OpenMP spec describes private (in the case of C++), in Section
> 2.15.3.3, as:
>
>| The new list item is initialized, or has an undefined initial value,
>| as if it had been locally declared without an initializer.
>
> "List item" here is an item in the private clause. The "new" list item
> is the one allocated for each thread.
>
> And later:
>
>| A variable of class type (or array thereof) that appears in a private
>| clause requires an accessible, unambiguous default constructor for
>| the class type.
>
>>> randomSample(). This is called in your openMP-loop and will
>>> therefore execute in parallel. This can't work. You need to make
>>> sure that the same object is not touched simultaneously from
>>> multiple threads. Either protect with locks (lock_guard<>), or
>>> duplicate the vector. And even better, remove the global. It is not
>>> sure where it is coming from, since you don't show complete
>>> compilable code.

>
0 new messages