编译器优化忽略循环中非无效的函数调用



我正在对一些代码进行基准测试,但当我设置优化标志时,编译器会在循环中忽略我的函数调用(bh_b = bh_b + bh_a + bh_a + bh_a + bh_a;(。当我删除优化标志时,代码运行良好。

我使用表达式模板编写了矩阵类

很抱歉上一篇文章无法复制。

代码

  • main.cpp
#include <iostream>
#include <chrono>
#include "matrix.h"
int main(){
int calc_num = 100000;

Matx<double, 3, 3> bh_a(1, 0, 0,
0, 1, 0,
0, 0, 1);
Matx<double, 3, 3> bh_b(0, 0, 0, 0, 0, 0, 0, 0, 0);

auto t_begin = std::chrono::high_resolution_clock::now();
for(int i=0; i<calc_num; ++i)
bh_b = bh_b + bh_a + bh_a + bh_a + bh_a;  // this part
auto t_end = std::chrono::high_resolution_clock::now();

std::cout << "Elapsed: " << std::chrono::duration_cast<std::chrono::microseconds>(t_end - t_begin).count() << "us" << std::endl;

for(int i=0; i<bh_b.cols; ++i) {
for (int j = 0; j < bh_b.cols; ++j)
std::cout << bh_b(i * bh_b.cols + j) << ' ';
std::cout << std::endl;
}

return 0;
}
  • 矩阵.h
#ifndef UNTITLED3_MATRIX_H
#define UNTITLED3_MATRIX_H
template <typename T, typename E>
class MatExpr{
public:
const T& operator () (int i) const { return static_cast<E const&>(*this)(i); }
};
template<typename T, int m, int n>
class Matx : public MatExpr<T, Matx<T, m, n>> {
public:
enum {
rows     = m,
cols     = n,
channels = rows*cols,
shortdim = (m < n ? m : n)
};

Matx(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8) : val{v0, v1, v2, v3, v4, v5, v6, v7, v8} {}

template <typename E>
Matx(MatExpr<T, E> const& expr){
for(int i=0; i<channels; ++i) val[i] = expr(i);
}

const T& operator () (int i) const { return val[i]; }

T val[m*n];
};
template <typename T, typename E1, typename E2>
class MatOp : public MatExpr<T, MatOp<T, E1, E2>> {
private:
E1 const& u;
E2 const& v;
public:
MatOp(E1 const& u, E2 const& v) : u(u), v(v) {}

const T& operator () (int i) const { return u(i) + v(i); }
};
template <typename T, typename E1, typename E2>
MatOp<T, E1, E2>
operator + (MatExpr<T, E1> const& u, MatExpr<T, E2> const& v){
return MatOp<T, E1, E2>(*static_cast<const E1*>(&u), *static_cast<const E2*>(&v));
}

#endif //UNTITLED3_MATRIX_H
  • CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(untitled3)
set(CMAKE_CXX_STANDARD 14)
add_executable(untitled3 main.cpp)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2" ) // Compiler optimization flag

输出

  • 无优化(正确输出(
Elapsed: 32308us
400000 0 0 
0 400000 0 
0 0 400000 
  • -O1
Elapsed: 16268us
0 0 0 
0 0 0 
0 0 0 
  • -O2-O3
Elapsed: 1us
0 0 0 
0 0 0 
0 0 0 

编译器

  • 在Mac操作系统上使用CLion
➜  ~ clang --version
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

代码包含未定义的行为。

在这条线上

const T& operator () (int i) const { return u(i) + v(i); }

您正在返回一个临时的地址(因为operator +生成一个临时(。

此处类似

const T& operator () (int i) const { return static_cast<E const&>(*this)(i); }

如果调用上面的,也可以生成临时。

一个可能的解决方案是按值返回(不知道这是否是正确的性能选择(。

相关内容

最新更新