表达模板:展开循环
Expression template : unroll loop
本文关键字:循环 更新时间:2023-10-16
我有相同的问题:表达模板:改善评估表达式的性能?
我的目的是展开此表达式的循环
auto && intermediate = A+D*C
for(int i= 0; i<10 ;i++)
intermediate = intermediate + B
Vector result = intermediate * E
我想在整个二进制表达式的中间树中,最后一个operator =(表达式)class矢量运行图形的检查使用我的代码,它只能无需循环即
编辑:循环引起的代码编译问题
如果我将循环输入主要,我有编译错误需要使用C 11
运行g -std = c 11 -o3 -fopenmp -wall -pedantic -pthread main.cpp&amp;&amp;./a.out
#include <vector>
#include <iostream>
template <typename TBase, typename Derived>
struct BaseExpression
{
Derived const& self() const { return static_cast<const Derived&>(*this); }
Derived & self() { return static_cast<Derived&>(*this); }
TBase operator[](size_t szIdx) const { return self()[szIdx]; }
size_t size() const {return self().size();}
};
template <typename TBase, typename Operator, typename OP1, typename OP2>
class Binary_Expression : public BaseExpression<TBase, Binary_Expression<TBase, Operator, OP1, OP2> >
{
public:
Binary_Expression(OP1 const & a, OP2 const & b) : op1(a), op2(b){}
TBase operator[] (size_t idx) const { return op(op1[idx], op2[idx]); }
size_t size() const { return op1.size() != 0 ? op1.size() : op2.size(); }
private:
const OP1 & op1;
const OP2 & op2;
Operator op;
};
template <typename TBase >
class Vector : public BaseExpression<TBase, Vector<TBase> >
{
public:
explicit Vector(size_t szSizeN) : m_xMemory(szSizeN){}
Vector(const Vector &orig): m_xMemory()
{
this->copy(orig);
}
Vector & operator=(const Vector &orig)
{
if (&orig != this)
{
Vector temp(orig);
this->swap(temp);
}
return *this;
}
Vector & operator=(TBase factor)
{
size_t szSizeN = size();
#pragma omp parallel for
for (size_t idx = 0; idx < szSizeN; idx++)
{
m_xMemory[idx] = factor;
}
return *this;
}
template <typename Expression>
Vector(const BaseExpression<TBase, Expression> &b) :m_xMemory(b.size())
{
size_t szSizeN = size();
#pragma omp parallel for
for (size_t idx = 0; idx < szSizeN; idx++)
{
m_xMemory[idx] = b[idx];
}
}
void swap(Vector &orig)
{
using std::swap;
swap(m_xMemory, orig.m_xMemory);
}
TBase operator[] (size_t idx) const { return m_xMemory[idx]; }
TBase & operator[] (size_t idx) { return m_xMemory[idx]; }
size_t size() const { return m_xMemory.size(); }
void print()
{
size_t szSizeN = size();
for (size_t idx = 0; idx < szSizeN; idx++)
{
std::cout << "Index=" << idx << "t" << "Value=" << m_xMemory[idx] << std::endl;
}
}
private:
void copy(const Vector &orig)
{
m_xMemory = orig.m_xMemory;
}
std::vector<TBase> m_xMemory;
};
template <typename TBase, typename E1, typename E2>
Binary_Expression<TBase, std::plus<TBase>, E1, E2> operator+(const BaseExpression<TBase, E1> & xE1, const BaseExpression< TBase, E2> & xE2)
{
return Binary_Expression<TBase, std::plus<TBase>, E1, E2>(xE1.self(), xE2.self());
}
int main()
{
Vector<double> x1(10);
Vector<double> x2(10);
Vector<double> x3(10);
x1 = 7.5;
x2 = 8.;
x3 = 4.2;
auto && intermediate = x1 + x2;
//compil error
/*
for (int i = 0; i< 10; i++)
{
intermediate = intermediate + x3;
}
*/
// inspection of the graph here
Vector<double> result = intermediate + x2;
result.print();
}
实际上,在我的最终设计中,我想写以下内容:
Vector<double> x1(10);
Vector<double> x2(10);
Vector<double> x3(10);
x1 = 7.5;
x2 = 8.;
x3 = 4.2;
Vector<double> intermediate = x1 + x2;
for (int i = 0; i < 5; ++i)
intermediate = intermediate + x3;
Vector<double> result = x1 + x3 + intermediate;
// finally into result I have the expression tree, and evaluate method which will make the graph inspection
result.evaluate();
预先感谢乔纳森
我恐怕它将行不通,因为链接的技术依赖于intermediate
变量捕获整个表达式的类型。因此,它看起来像Sum<Mult<Vector,Vector>>
(在此简化)。但是类型无法改变for循环的每次迭代。
我看到替代方案:
不要将表达式捕获为类型,而是类型的运行时结构,例如vectorexpression。这将产生性能影响,因为您必须在运行时分析表达式图并限制您可以执行的优化类型。
第二个选择是使用模板元编程编写自己的循环(每个步骤都有新的类型)。
折叠功能的示例(这是您想要的)。我们必须使用折叠函数,因为不支持函数的部分专业化:
#include <utility>
template <int N, class V, class F>
struct foldf {
auto operator()(V v, F&& f) -> decltype(auto) {
auto next = f(v);
return foldf<N - 1, decltype(next), F>()(next, std::move(f));
}
};
template <class V, class F>
struct foldf<0, V, F> {
auto operator()(V v, F&& f) -> decltype(auto) {
return v;
}
};
// just a helper to make usage simpler
template <int N>
class Repeat{};
template <int N, class V, class F>
auto fold(Repeat<N> tag, V v, F&& f) -> decltype(auto) {
return foldf<N, V, F>()(v, std::move(f));
}
要证明它可以做我们想要的,让我们添加此代码:
template <class T>
class Test {
};
class Other{};
template <class T>
auto wrap(T t) -> decltype(auto) {
return Test<T>();
}
int main() {
auto v = fold(Repeat<3>(), 0, [](auto t){
return wrap(t);
});
Other x = v;
}
结果应为 tmp.cpp:42:11: error: no viable conversion from 'Test<Test<Test<int> > >' to 'Other'
,显示了保留类型。
相关文章:
- 如何循环打印顶点结构
- 如何在C++中从两个单独的for循环中添加两个数组
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 正在尝试了解输入验证循环
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 循环后如何继续阅读
- Ardunio UNO解决了多个重叠的定时器循环
- Eigen如何在容器循环中干净地附加矩阵
- 在某些循环内使用vector.push_back时出现分段错误
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 为什么我的for循环不能正确获取argv
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- while循环中while循环的时间复杂度是多少
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 为什么在这个代码结束循环中没有得到结束
- 在基于范围的for循环中使用结构化绑定声明
- 用于C++中带有数组和指针的循环
- 循环中的随机函数
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 在循环C++中指定字符串之后,不会打印该字符串