179 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
		
		
			
		
	
	
			179 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
|  | /*
 | ||
|  |  * 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 "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() { 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; | ||
|  | 		} | ||
|  | 	} | ||
|  | } |