std::string ToString(double value, size_t iCount, size_t fCount) { assert(iCount > 0); if(value > 0) { std::stringstream ss; ss << std::setprecision(fCount) << std::fixed << value; return ExpandToLeft(ss.str(), iCount + fCount + (fCount > 0 ? 1 : 0)); } else { return ExpandToLeft("", iCount + fCount + 1); } }
std::string PerformanceMeasurerStorage::Report(bool sse42_, bool align, bool raw) const { struct Statistic { std::pair<Pm, Pm> simd; std::pair<Pm, Pm> base; Pm sse42; std::pair<Pm, Pm> sse2; std::pair<Pm, Pm> ssse3; std::pair<Pm, Pm> sse41; std::pair<Pm, Pm> avx2; std::pair<Pm, Pm> vsx; }; typedef std::map<std::string, Statistic> StatisticMap; StatisticMap statistic; double timeMax = 0; size_t sizeMax = 8; bool sse2 = false, ssse3 = false, sse41 = false, sse42 = false, avx2 = false, vsx = false; for(Map::const_iterator it = _map.begin(); it != _map.end(); ++it) { const std::string & desc = it->second->Description(); std::string name = FunctionShortName(desc); Statistic & s = statistic[name]; if(desc.find("Simd::") == std::string::npos && desc.find("Simd") == 0) { if(Aligned(desc)) s.simd.first = *it->second; else s.simd.second = *it->second; } if(desc.find("Simd::Base::") != std::string::npos) { if(Aligned(desc)) s.base.first = *it->second; else s.base.second = *it->second; } if(desc.find("Simd::Sse2::") != std::string::npos || desc.find("Simd::Sse::") != std::string::npos) { if(Aligned(desc)) s.sse2.first = *it->second; else s.sse2.second = *it->second; sse2 = true; } if(desc.find("Simd::Ssse3::") != std::string::npos) { if(Aligned(desc)) s.ssse3.first = *it->second; else s.ssse3.second = *it->second; ssse3 = true; } if(desc.find("Simd::Sse41::") != std::string::npos) { if(Aligned(desc)) s.sse41.first = *it->second; else s.sse41.second = *it->second; sse41 = true; } if(desc.find("Simd::Sse42::") != std::string::npos) { s.sse42 = *it->second; sse42 = true && sse42_; } if(desc.find("Simd::Avx2::") != std::string::npos || desc.find("Simd::Avx::") != std::string::npos) { if(Aligned(desc)) s.avx2.first = *it->second; else s.avx2.second = *it->second; avx2 = true; } if(desc.find("Simd::Vsx::") != std::string::npos) { if(Aligned(desc)) s.vsx.first = *it->second; else s.vsx.second = *it->second; vsx = true; } timeMax = std::max(timeMax, it->second->Average()); sizeMax = std::max(name.size(), sizeMax); } const size_t ic = 1 + (size_t)::log10(std::max(timeMax*1000, 1.0)); const size_t ir = 3; const size_t fc = 3; std::vector<std::string> statistics; for(StatisticMap::const_iterator it = statistic.begin(); it != statistic.end(); ++it) { const Statistic & s = it->second; std::stringstream ss; ss << ExpandToRight(it->first, sizeMax) << " | "; ss << ToString(s.simd.first.Average()*1000.0, ic, fc) << " "; ss << ToString(s.base.first.Average()*1000.0, ic, fc) << " "; if(sse2) ss << ToString(s.sse2.first.Average()*1000.0, ic, fc) << " "; if(ssse3) ss << ToString(s.ssse3.first.Average()*1000.0, ic, fc) << " "; if(sse41) ss << ToString(s.sse41.first.Average()*1000.0, ic, fc) << " "; if(sse42) ss << ToString(s.sse42.Average()*1000.0, ic, fc) << " "; if(avx2) ss << ToString(s.avx2.first.Average()*1000.0, ic, fc) << " "; if(vsx) ss << ToString(s.vsx.first.Average()*1000.0, ic, fc) << " "; ss << "| "; if(sse2 || ssse3 || sse41 || sse42 || avx2 || vsx) { if(sse2) ss << ToString(Relation(s.base.first, s.sse2.first), ir, fc) << " "; if(ssse3) ss << ToString(Relation(s.base.first, s.ssse3.first), ir, fc) << " "; if(sse41) ss << ToString(Relation(s.base.first, s.sse41.first), ir, fc) << " "; if(sse42) ss << ToString(Relation(s.base.first, s.sse42), ir, fc) << " "; if(avx2) ss << ToString(Relation(s.base.first, s.avx2.first), ir, fc) << " "; if(vsx) ss << ToString(Relation(s.base.first, s.vsx.first), ir, fc) << " "; ss << "| "; } if(sse2 && (ssse3 || sse41)) { if(ssse3) ss << ToString(Relation(s.sse2.first, s.ssse3.first), ir, fc) << " "; if(sse41) ss << ToString(Relation(s.sse2.first, s.sse41.first), ir, fc) << " "; ss << "| "; } if((sse2 || ssse3 || sse41) && avx2) { if(sse2) ss << ToString(Relation(s.sse2.first, s.avx2.first), ir, fc) << " "; if(ssse3) ss << ToString(Relation(s.ssse3.first, s.avx2.first), ir, fc) << " "; if(sse41) ss << ToString(Relation(s.sse41.first, s.avx2.first), ir, fc) << " "; ss << "| "; } if(align) { ss << ToString(Relation(s.base.second, s.base.first), ir, fc) << " "; if(sse2) ss << ToString(Relation(s.sse2.second, s.sse2.first), ir, fc) << " "; if(ssse3) ss << ToString(Relation(s.ssse3.second, s.ssse3.first), ir, fc) << " "; if(sse41) ss << ToString(Relation(s.sse41.second, s.sse41.first), ir, fc) << " "; if(avx2) ss << ToString(Relation(s.avx2.second, s.avx2.first), ir, fc) << " "; if(vsx) ss << ToString(Relation(s.vsx.second, s.vsx.first), ir, fc) << " "; ss << "| "; } statistics.push_back(ss.str()); } std::sort(statistics.begin(), statistics.end()); std::stringstream header; header << ExpandToRight("Function", sizeMax) << " | "; header << ExpandToLeft("Simd", ic + fc + 1) << " "; header << ExpandToLeft("Base", ic + fc + 1) << " "; if(sse2) header << ExpandToLeft("Sse2", ic + fc + 1) << " "; if(ssse3) header << ExpandToLeft("Ssse3", ic + fc + 1) << " "; if(sse41) header << ExpandToLeft("Sse41", ic + fc + 1) << " "; if(sse42) header << ExpandToLeft("Sse42", ic + fc + 1) << " "; if(avx2) header << ExpandToLeft("Avx2", ic + fc + 1) << " "; if(vsx) header << ExpandToLeft("Vsx", ic + fc + 1) << " "; header << "| "; if(sse2 || ssse3 || sse41 || sse42 || avx2 || vsx) { if(sse2) header << ExpandToLeft("B/S2", ir + fc + 1) << " "; if(ssse3) header << ExpandToLeft("B/S3", ir + fc + 1) << " "; if(sse41) header << ExpandToLeft("B/S41", ir + fc + 1) << " "; if(sse42) header << ExpandToLeft("B/S42", ir + fc + 1) << " "; if(avx2) header << ExpandToLeft("B/A2", ir + fc + 1) << " "; if(vsx) header << ExpandToLeft("B/Vs", ir + fc + 1) << " "; header << "| "; } if(sse2 && (ssse3 || sse41)) { if(ssse3) header << ExpandToLeft("S2/S3", ir + fc + 1) << " "; if(sse41) header << ExpandToLeft("S2/S41", ir + fc + 1) << " "; header << "| "; } if((sse2 || ssse3 || sse41) && avx2) { if(sse2) header << ExpandToLeft("S2/A2", ir + fc + 1) << " "; if(ssse3) header << ExpandToLeft("S3/A2", ir + fc + 1) << " "; if(sse41) header << ExpandToLeft("S41/A2", ir + fc + 1) << " "; header << "| "; } if(align) { header << ExpandToLeft("B:U/A", ir + fc + 1) << " "; if(sse2) header << ExpandToLeft("S2:U/A", ir + fc + 1) << " "; if(ssse3) header << ExpandToLeft("S3:U/A", ir + fc + 1) << " "; if(sse41) header << ExpandToLeft("S41:U/A", ir + fc + 1) << " "; if(avx2) header << ExpandToLeft("A2:U/A", ir + fc + 1) << " "; if(vsx) header << ExpandToLeft("Vs:U/A", ir + fc + 1) << " "; header << "| "; } std::stringstream separator; for(size_t i = 0; i < header.str().size(); ++i) separator << "-"; std::stringstream report; if(raw) { report << std::endl << "Raw performance report:" << std::endl << std::endl; for(Map::const_iterator it = _map.begin(); it != _map.end(); ++it) report << it->second->Statistic() << std::endl; } report << std::endl << "Performance report:" << std::endl << std::endl; report << separator.str() << std::endl; report << header.str() << std::endl; report << separator.str() << std::endl; for(size_t i = 0; i < statistics.size(); ++i) report << statistics[i] << std::endl; report << separator.str() << std::endl; return report.str(); }