利用模板元编程实现解循环优化

简介

在《C++ Templates: The Complete Guide》一书中(以下简称书),提出了模板元编程最早的实际应用之一:在数值运算中进行解循环优化。

而本文的标题是噱头!本文的真正目的是指出这种优化措施在增加复杂性的同时,并不一定能明显改善效率。应当谨慎使用该技术——默认不使用该技术,在点积计算确实是效率瓶颈时考虑采用该技术,并认真测试该技术是否真能提高效率。

背景

数值运算库中常常需要提供向量点积(dot_product)运算。其定义用C++代码描述也许更清楚~

template<typename T>
T dot_product(int dim,const T v1[],const T v2[]) {
  T result=0;
  for (int i=0;i<dim;++i)
    result += v1[i]*v2[i];
  return result;
}
我们可以使用这个函数,求2个向量的点积int v1[] = {1,2,3};
int v2[] = {4,5,6};
int r1 = dot_product(3,v1,v2);
得到r1=32

书中指出:“这个结果是正确的,但是在要求高效率的应用中,它耗费了太多的时间”,对于这类特殊的问题,“简单的把循环展开”,如:r1=v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]

“反而会好得多”。

如何便捷的展开循环?将每个dot_product(dim,...) 手工重写成展开式?还是设计一整套函数: dot_product_dim_2,dot_product_dim_3,... ?

无疑这是一个冗长乏味易出错的方案。

书中提出了一种使用模板元编程解决该问题的方案,让我们来看看他是怎么做的。

模板元编程——解循环

// 首先是递归模板
template<int DIM,typename T>
struct DotProduct {
  static T execute(const T v1[],const T v2[]);
}
template<int DIM,typename T>
T DotProduct<DIM,T>::execute(const T v1[],const T v2[]) {
  return v1[0]*v2[0] + DotProduct<DIM-1,T>::execute(v1+1,v2+1);
}
// 递归边界模板
template<typename T>
struct DotProduct<1,T> {
  static T execute(const T v1[],const T v2[]);
}
template<typename T>
T DotProduct<1,T>::execute(const T v1[],const T v2[]) {
  return v1[0]*v2[0];
}
我们可以使用DotProduct 来进行点积计算了:int v1[] = {1,2,3}; int v2[] = {4,5,6};
int r2 = DotProduct<3,int>::execute(v1,v2);

时间: 2024-11-03 11:32:00

利用模板元编程实现解循环优化的相关文章

【C/C++学院】0816-引用包装器/仿函数/转义字符 R”()”/using别名/模板元编程 比递归优化/智能指针/多线程/静态断言以及调试技能的要求 assert

引用包装器  std::ref(变量) #include<iostream> template<class T> void com(T arg)//模板函数,引用无效,引用包装器 { std::cout <<"com ="<< &arg << "\n"; arg++; } void main() { int count = 10; int & rcount = count; com(coun

C++之:模板元编程(一)

一.概念 利用模板特化机制实现编译期条件选择结构,利用递归模板实现编译期循环结构,模板元程序则由编译器在编译期解释执行. 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数.返回值取得任意类型. 模板是一种对类型进行参数化的工具: 通常有两种形式:函数模板和类模板: 函数模板针对仅参数类型不同的函数: 类模板针对仅数据成员和成员函数类型不同的类. 使用模板的目的就是能够让程序员编写与类型无关的代码.比如编写了一个交换两个整型

C++箴言:谨慎使用模板元编程

template metaprogramming (TMP)(模板元编程)是写 template-based(基于模板)的运行于编译期间的 C++ 程序的过程.考虑一下:一个 template metaprogram(模板元程序)是用 C++ 写的运行于 C++ 编译器中的程序.当一个 TMP 程序运行完成,它的输出--从 templates(模板)实例化出的 C++ 源代码片断--随后被正常编译. 如果你仅把它看作古怪的特性而没有打动你,那你就不会对它有足够的深入的思考. C++ 并不是为 t

Functional Programming与C++的模板元编程

先来看一个例子: #include <stdio.h> template <int depth> class Fibnacci { public: static const int value = Fibnacci<depth-1>::value + Fibnacci<depth-2>::value; }; template <> class Fibnacci<0> { public: static const int value =

初探模板元编程

关于模板元编程的知识也有所了解,相关的书籍也看过几本,但是至今还没有亲手写过一个模板元程序,原因就是没有一个合适的机会应用模板元编程技术,今天在CSDN上看见一个帖子,定义常量字符串 char *p="Hello,Word!"; 既然是常量字符串,应该可以在编译期知道p的长度,在编译期间如何得到? 这个问题,我首先想到用模板元编程来实现,于是尝试编写一个. 真正用模板元编程时,才发现自己完全没有思路,不知道如何解决.于是下定决心学好模板元编程,这个问题就是我学习的动力,希望以后能够使用

C++之:模板元编程(三) 默认模板参数

一.类模板的默认模板参数原则 1.可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值.函数模板和类模板都可以为模板的非类型形参提供默认值. 2.类模板的类型形参默认值形式为: template<class T1, class T2=int> class A{}; 为第二个模板类型形参T2提供int型的默认值. 3.类模板类型形参默认值和函数的默认参数一样,如果有多个类型形参则从第一个形参设定了默认值之后的所有模板形参都要设定默认值,比如 template<class

使用模板元编程快速的得到斐波那契数。。

这是一种将运行时消耗转移到编译器消耗的方法,是c++模板的一种应用. 当你的程序运行时效率需要特别高的时候,可以考虑这样的方法. 模板实例化的时候需要常量: #include <iostream> using namespace std; template < unsigned N > struct Fib { enum { Val = Fib<N-1>::Val + Fib<N-2>::Val //递归.. }; }; template<> /

C++之:模板元编程(二) 模板形参

一.模板形参概述 有三种类型的模板形参:类型形参,非类型形参和模板形参. 二.类型形参 2.1 .类型模板形参 类型形参由关见字class或typename后接说明符构成,如template<class T> void h(T a){};其中T就是一个类型形参,类型形参的名字由用户自已确定.模板形参表示的是一个未知的类型.模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型说明符或类类型说明符的使用方式完全相同,即可以用于指定返回类型,变量声明等. 2.2. 不能为同一个模板类型形参指

引用内部函数绑定机制,R转义字符,C++引用,别名,模板元,宏,断言,C++多线程,C++智能指针

 1.引用内部函数绑定机制 #include<iostream> #include<functional>   usingnamespacestd; usingnamespacestd::placeholders;   //仿函数,创建一个函数指针,引用一个结构体内部或者一个类内部的共有函数 structMyStruct {    voidadd(inta)    {        cout <<a <<endl;    }    voidadd2(in