192 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
/* ----------------------------------------------------------------------------
 | 
						|
 | 
						|
 * GTSAM Copyright 2010, Georgia Tech Research Corporation, 
 | 
						|
 * Atlanta, Georgia 30332-0415
 | 
						|
 * All Rights Reserved
 | 
						|
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
 | 
						|
 | 
						|
 * See LICENSE for the license information
 | 
						|
 | 
						|
 * -------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/*
 | 
						|
 * timeSymbolMaps.cpp
 | 
						|
 *
 | 
						|
 *  Created on: Jan 20, 2010
 | 
						|
 *      Author: richard
 | 
						|
 */
 | 
						|
 | 
						|
#include <boost/unordered_map.hpp>
 | 
						|
#include <string>
 | 
						|
#include <boost/timer.hpp>
 | 
						|
#include <boost/lexical_cast.hpp>
 | 
						|
#include <vector>
 | 
						|
#include <map>
 | 
						|
 | 
						|
#include <gtsam/nonlinear/Key.h>
 | 
						|
 | 
						|
using namespace std;
 | 
						|
using namespace boost;
 | 
						|
using namespace gtsam;
 | 
						|
 | 
						|
template<class T>
 | 
						|
class SymbolMapExp {
 | 
						|
private:
 | 
						|
	typedef map<unsigned char, vector<T> > Map;
 | 
						|
	typedef vector<T> Vec;
 | 
						|
 | 
						|
	Map values_;
 | 
						|
 | 
						|
public:
 | 
						|
	typedef pair<Symbol, T> value_type;
 | 
						|
 | 
						|
	SymbolMapExp() {}
 | 
						|
 | 
						|
	T& at(const Symbol& key) {
 | 
						|
		typename Map::iterator it = values_.find(key.chr());
 | 
						|
		if(it != values_.end())
 | 
						|
			return it->second.at(key.index());
 | 
						|
		else
 | 
						|
			throw invalid_argument("Key " + (string)key + " not present");
 | 
						|
	}
 | 
						|
 | 
						|
	void set(const Symbol& key, const T& value) {
 | 
						|
		Vec& vec(values_[key.chr()]);
 | 
						|
		//vec.reserve(10000);
 | 
						|
		if(key.index() >= vec.size()) {
 | 
						|
			vec.reserve(key.index()+1);
 | 
						|
			vec.resize(key.index());
 | 
						|
			vec.push_back(value);
 | 
						|
		} else
 | 
						|
			vec[key.index()] = value;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
template<class T>
 | 
						|
class SymbolMapBinary : public std::map<Symbol, T> {
 | 
						|
private:
 | 
						|
	typedef std::map<Symbol, T> Base;
 | 
						|
public:
 | 
						|
	SymbolMapBinary() : std::map<Symbol, T>() {}
 | 
						|
 | 
						|
	T& at(const Symbol& key) {
 | 
						|
		typename Base::iterator it = Base::find(key);
 | 
						|
		if (it == Base::end())
 | 
						|
			throw(std::invalid_argument("SymbolMap::[] invalid key: " + (std::string)key));
 | 
						|
		return it->second;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
struct SymbolHash : public std::unary_function<Symbol, std::size_t> {
 | 
						|
	std::size_t operator()(Symbol const& x) const {
 | 
						|
		std::size_t seed = 0;
 | 
						|
		boost::hash_combine(seed, x.chr());
 | 
						|
		boost::hash_combine(seed, x.index());
 | 
						|
		return ((size_t(x.chr()) << 24) & x.index());
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
template<class T>
 | 
						|
class SymbolMapHash : public boost::unordered_map<Symbol, T, SymbolHash> {
 | 
						|
public:
 | 
						|
	SymbolMapHash() : boost::unordered_map<Symbol, T, SymbolHash>(60000) {}
 | 
						|
};
 | 
						|
 | 
						|
struct Value {
 | 
						|
	double v;
 | 
						|
	Value() : v(0.0) {}
 | 
						|
	Value(double vi) : v(vi) {}
 | 
						|
	operator string() { return lexical_cast<string>(v); }
 | 
						|
	bool operator!=(const Value& vc) { return v != vc.v; }
 | 
						|
};
 | 
						|
 | 
						|
#define ELEMS 3000
 | 
						|
#define TIMEAT 300
 | 
						|
 | 
						|
int main(int argc, char *argv[]) {
 | 
						|
	timer tmr;
 | 
						|
 | 
						|
	// pre-allocate
 | 
						|
	cout << "Generating test data ..." << endl;
 | 
						|
	vector<pair<Symbol, Value> > values;
 | 
						|
	for(size_t i=0; i<ELEMS; i++) {
 | 
						|
		values.push_back(make_pair(Symbol('a',i), (double)i));
 | 
						|
		values.push_back(make_pair(Symbol('b',i), (double)i));
 | 
						|
		values.push_back(make_pair(Symbol('c',i), (double)i));
 | 
						|
	}
 | 
						|
 | 
						|
	// time binary map
 | 
						|
	cout << "Timing binary map ..." << endl;
 | 
						|
	{
 | 
						|
		SymbolMapBinary<Value> binary;
 | 
						|
		for(size_t i=0; i<ELEMS*3; ) {
 | 
						|
			size_t stop = i + TIMEAT;
 | 
						|
			tmr.restart();
 | 
						|
			for( ; i<stop; i++)
 | 
						|
				binary.insert(values[i]);
 | 
						|
			double time = tmr.elapsed();
 | 
						|
			cout << i << " values, avg " << (time/(double)TIMEAT)*1e6 << " mu-s per insert" << endl;
 | 
						|
 | 
						|
			tmr.restart();
 | 
						|
			for(size_t j=0; j<i; j++)
 | 
						|
				if(values[j].second != binary[values[j].first]) {
 | 
						|
					cout << "Wrong value!  At key " << (string)values[j].first <<
 | 
						|
							" expecting " << (string)values[j].second <<
 | 
						|
							" got " << (string)binary[values[j].first] << endl;
 | 
						|
				}
 | 
						|
			time = tmr.elapsed();
 | 
						|
			cout << i << " values, avg " << (time)*1e3 << " ms per lookup" << endl;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// time hash map
 | 
						|
	cout << "Timing hash map ..." << endl;
 | 
						|
	{
 | 
						|
		SymbolMapHash<Value> hash;
 | 
						|
		for(size_t i=0; i<ELEMS*3; ) {
 | 
						|
			size_t stop = i + TIMEAT;
 | 
						|
			tmr.restart();
 | 
						|
			for( ; i<stop; i++)
 | 
						|
				hash.insert(values[i]);
 | 
						|
			double time = tmr.elapsed();
 | 
						|
			cout << i << " values, avg " << (time/(double)TIMEAT)*1e6 << " mu-s per insert" << endl;
 | 
						|
 | 
						|
			tmr.restart();
 | 
						|
			for(size_t j=0; j<i; j++)
 | 
						|
				if(values[j].second != hash[values[j].first]) {
 | 
						|
					cout << "Wrong value!  At key " << (string)values[j].first <<
 | 
						|
							" expecting " << (string)values[j].second <<
 | 
						|
							" got " << (string)hash[values[j].first] << endl;
 | 
						|
				}
 | 
						|
			time = tmr.elapsed();
 | 
						|
			cout << i << " values, avg " << (time/(double)i)*1e6 << " mu-s per lookup" << endl;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// time experimental map
 | 
						|
	cout << "Timing experimental map ..." << endl;
 | 
						|
	{
 | 
						|
		SymbolMapExp<Value> experimental;
 | 
						|
		for(size_t i=0; i<ELEMS*3; ) {
 | 
						|
			size_t stop = i + TIMEAT;
 | 
						|
			tmr.restart();
 | 
						|
			for( ; i<stop; i++)
 | 
						|
				experimental.set(values[i].first, values[i].second);
 | 
						|
			double time = tmr.elapsed();
 | 
						|
			cout << i << " values, avg " << (time/(double)TIMEAT)*1e6 << " mu-s per insert" << endl;
 | 
						|
 | 
						|
			tmr.restart();
 | 
						|
			for(size_t j=0; j<i; j++)
 | 
						|
				if(values[j].second != experimental.at(values[j].first)) {
 | 
						|
					cout << "Wrong value!  At key " << (string)values[j].first <<
 | 
						|
							" expecting " << (string)values[j].second <<
 | 
						|
							" got " << (string)experimental.at(values[j].first) << endl;
 | 
						|
				}
 | 
						|
			time = tmr.elapsed();
 | 
						|
			cout << i << " values, avg " << (time/(double)i)*1e6 << " mu-s per lookup" << endl;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 |