Community
cancel
Showing results for 
Search instead for 
Did you mean: 
velvia
Beginner
100 Views

Optimization problems with std::array maybe due to RVO

Hi,

I discovered a source of slowdown in my program, due to the usage of std::array. To gain a better understanding of what was going on, I have used my own implementation of std::array, and the slowdown disappeared. Unfortunately, I can't show you the program I am working on due to some non disclosure agreement. But I've managed to track down the problem and put it in a simple file.

When you compile the file shown below with

icpc -c -std=c++11 -Ofast -xHost -ansi-alias -qopt-report=2 ode.cpp -o ode.o

and look at the optimization report, the generated function is

ode(StaticVector<double, 2UL> *, const StaticVector<double, 2UL> &)

But if you comment out what is in between the "culprit" comments, all the constructors and assignements, the function does have a new signature

ode(const StaticVector<double, 2UL> &)

My guess is that it has to do with return value optimization. Could you please explain me why we have such a difference?

Best regards,

Francois

#include <cstddef>
#include <utility>
#include <cmath>

template <typename T, std::size_t n>
class StaticVector {
private:
    T data_;
public:
    StaticVector() = default;
// Culprit
    StaticVector(const StaticVector& v) {
        for (std::size_t k = 0; k < n; ++k) {
            data_ = v.data_;
        }
    }
    StaticVector(StaticVector&& v) {
        for (std::size_t k = 0; k < n; ++k) {
            data_ = std::move(v.data_);
        }
    }
    StaticVector& operator=(const StaticVector& v) {
        for (std::size_t k = 0; k < n; ++k) {
            data_ = v.data_;
        }
        return *this;
    }
    StaticVector& operator=(StaticVector&& v) {
        for (std::size_t k = 0; k < n; ++k) {
            data_ = std::move(v.data_);
        }
        return *this;
    }
// Culprit
    T& operator[](std::size_t k) {
        return data_;
    }
    const T& operator[](std::size_t k) const {
        return data_;
    }
};

StaticVector<double, 2> ode(const StaticVector<double, 2>& y) {
    StaticVector<double, 2> dy_dt;
    dy_dt[0] = cos(y[0]);
    dy_dt[1] = sin(y[1]);

    return dy_dt;
}

 

0 Kudos
3 Replies
velvia
Beginner
100 Views

Hi,

I have managed to make the example much more simple. The following code

class Test {
public:
	Test() = default;
	Test(const Test& x);
};

Test f() {
	auto x = Test( );

	return x;
}

does generate RVO but this one

class Test {
public:
	Test() = default;
};

Test f() {
	auto x = Test( );

	return x;
}

does not and nothing says in the standard that it should not. It makes all std::array<T, n> implementations that I know of miss return value optimization. I believe that this should be filed as an "optimization bug" of the compiler.

Kittur_G_Intel
Employee
100 Views

Hi Velvia,
This is an interesting issue and looks like the compiler does RVO involving copy constructors (from your first case) but need to find out more on your other case with the developers. I'll update you accordingly, thanks
_Kittur

100 Views

Hi,

I have the exact same problem with icpc 17 with -O3. If the copy constructor is not declared/defined as the compiler should have generated, it can result in a catastrophic degradation of performance (x3 times slower in my moderately complicated case). Any news about this performance issue ?

Bérenger

Reply