over-eager evaluation(急速评估)

over-eager evaluation(急速评估) 是一种将操作提前执行,以减少未来计算成本的优化技术。它有两种常见的实现方法:caching(高速缓存)和 prefetching(预先取出)。

caching

是一种缓存已经计算出来而有可能再被需要的值的方法。它的好处是,可以避免重复的计算,提高程序的效率。它的缺点是,需要额外的空间来存储缓存的值,而且可能会导致缓存的值过期或失效。

class Employee {
public:
  // 根据员工姓名返回办公室编号,如果 map 不存在,就创建并填充它
  int findCubicleNumber(const string& employeeName) const {
    if (!cubicleMap) {
      cubicleMap = new map<string, int>();
      // 从数据库中读取所有员工的姓名和办公室编号,存入 map 中
      ...
    }
    // 在 map 中查找员工姓名,返回对应的办公室编号
    auto it = cubicleMap->find(employeeName);
    if (it != cubicleMap->end()) {
      return it->second;
    } else {
      return -1; // 表示找不到该员工
    }
  }
  ...
private:
  mutable map<string, int>* cubicleMap; // 员工姓名和办公室编号的映射
};

        该策略就是使用一个局部缓存(local cache),将相对昂贵的“数据库查询动作”以相对价廉的“内存内数据结构查找动作”取代之。倘若我们假设房间号码频繁被需要,而且这是正确的假设,那么在 findCubicleNumber 内使用 cache, 应该可以降低“返回一个职员的房间号码”的平均成本。

prefetching

        是一种预先取出未来可能会用到的值的方法。它的好处是,可以避免等待数据的传输,提高程序的效率。它的缺点是,需要额外的带宽来传输数据,而且可能会导致取出的数据没有用上或过早被替换。

template<class T>
class DynArray{...}; //template,用于元素类型为T的动态数组
 
DynArray<double> a; //此时,只有a[0]是合法的数组元素
 
a[22] = 3.5;		 //a被自动扩张,此时有效索引0-22
 
a[32] = 0;			//a再度扩张自己,此刻a[0]-a[32]都有效
template<class T>
T& DynArray<T>::operator[](int index)
{
	if(index < 0)
		throw an exception;  //负值索引无效
	
	if(index > 当前最大的索引值)
    {
		调用new分配足够内存;   //调用new会触发operator new
						     			     
	}
	return 返回该位置上元素;
}

  此做法是在每次需要增加数组大小时就调用 new,但是 new 会调用 operator new,而 operator new(以及 operator delete) 通常代价昂贵,因为它们通常会调用底层操作系统,而“系统调用”往往比“进程(process)内的函数调用”速度慢。所以我们应该尽可能不要采用系统调用。
  此处我们可以使用 over-eager evaluation(超急评估)策略,理由是: 如果我们此刻必须增加数组大小以接纳索引 i,“locality of reference法则”建议我们未来或许还需再增加大小,以接纳比 i 稍大的索引。为避免第二次(预期中的)扩张所需要的内存分配成本,我们把 DynArray 的大小调整到比它目前所需的大小(使索引i 有效)再大一些,而我们希望未来的扩张落入我们此刻所增加的弹性范围内。例如, DynArray::operator[]可撰写为如下:

template<class T>
T& DynArray<T>::operator[](int index)
{
	if(index < 0)
		throw an exception;
	
	if(index > 当前最大的索引值)
		int diff = index - 当前最大的索引值;
		调用new分配足够的额外内存,分配index+diff这么大的内存,相当于容量翻倍了;
	
	return index位置上的元素;
}


DynArray<double> a; 
 
a[22] = 3.5;		 //new 被调用以扩张a的空间,使能容纳索引44,a的逻辑大小为23
 
a[32] = 0;			 //a的逻辑大小改变,以允许a[32]存在,但没有在调用new

        这两种技术的主要目的都是提前获取数据或计算结果,以便在实际需要时能够更快地访问。然而,它们的实现方式和应用场景有所不同。 Caching 更关注保存已经计算的结果,而 Prefetching 更注重在需要时提前加载数据。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值