【发布时间】:2013-04-15 07:06:50
【问题描述】:
在previous question 上我想优化此功能:
static
lvh_distance levenshtein_distance( const std::string & s1, const std::string & s2 )
{
const size_t len1 = s1.size(), len2 = s2.size();
std::vector<unsigned int> col( len2+1 ), prevCol( len2+1 );
const size_t prevColSize = prevCol.size();
for( unsigned int i = 0; i < prevColSize; i++ )
prevCol[i] = i;
for( unsigned int i = 0, j; i < len1; ++i )
{
col[0] = i+1;
const char s1i = s1[i];
for( j = 0; j < len2; ++j )
{
const auto minPrev = 1 + std::min( col[j], prevCol[1 + j] );
col[j+1] = std::min( minPrev, prevCol[j] + ( s1i == s2[j] ? 0 : 1 ) );
}
col.swap( prevCol );
}
return prevCol[len2];
}
一位用户评论说我可以用((s1i - s2[j]) & 0x80) >> 7 替换s1i == s2[j] ? 0 : 1 以防止条件跳转。这个技巧是错误的,用户删除了他的评论,但我想知道是否真的有办法做到这一点。
【问题讨论】:
-
发表评论的用户是否查看了编译器的优化输出,看看您的代码中是否真的存在条件跳转?
-
@SteveJessop 添加了其他问题的链接:是的,程序集输出显示在那里。
-
小型局部优化是 编译器 最擅长的。我会更担心大小和数组元素的所有额外副本。 更多变量真的可以让代码更快吗?
-
@rhalbersma:感谢您的链接。不幸的是,你不能用向量做到这一点。
reserve不会改变向量的大小,只会改变容量,因此 init 循环会越界访问。不过,您可以使用boost::counting_iterator或等效项来初始化向量,以避免对向量数据进行两次传递。 -
@SteveJessop 为什么不让第一个
for循环一个reserve,然后是prevCol.push_back(i)?col类似,它也可以在循环内使用push_back,之前使用reserve。
标签: c++ performance optimization comparison branch-prediction