【发布时间】:2017-12-06 01:55:27
【问题描述】:
我一直在尝试在某些条件下提高strcmp 的性能。然而,不幸的是,我什至无法获得普通香草strcmp 的实现,其性能与库实现一样好。
我看到了similar question,但答案说不同之处在于编译器优化了字符串文字的比较。我的测试不使用字符串文字。
这是实现(comparisons.cpp)
int strcmp_custom(const char* a, const char* b) {
while (*b == *a) {
if (*a == '\0') return 0;
a++;
b++;
}
return *b - *a;
}
这是测试驱动程序(driver.cpp):
#include "comparisons.h"
#include <array>
#include <chrono>
#include <iostream>
void init_string(char* str, int nChars) {
// 10% of strings will be equal, and 90% of strings will have one char different.
// This way, many strings will share long prefixes so strcmp has to exercise a bit.
// Using random strings still shows the custom implementation as slower (just less so).
str[nChars - 1] = '\0';
for (int i = 0; i < nChars - 1; i++)
str[i] = (i % 94) + 32;
if (rand() % 10 != 0)
str[rand() % (nChars - 1)] = 'x';
}
int main(int argc, char** argv) {
srand(1234);
// Pre-generate some strings to compare.
const int kSampleSize = 100;
std::array<char[1024], kSampleSize> strings;
for (int i = 0; i < kSampleSize; i++)
init_string(strings[i], kSampleSize);
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < kSampleSize; i++)
for (int j = 0; j < kSampleSize; j++)
strcmp(strings[i], strings[j]);
auto end = std::chrono::high_resolution_clock::now();
std::cout << "strcmp - " << (end - start).count() << std::endl;
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < kSampleSize; i++)
for (int j = 0; j < kSampleSize; j++)
strcmp_custom(strings[i], strings[j]);
end = std::chrono::high_resolution_clock::now();
std::cout << "strcmp_custom - " << (end - start).count() << std::endl;
}
还有我的makefile:
CC=clang++
test: driver.o comparisons.o
$(CC) -o test driver.o comparisons.o
# Compile the test driver with optimizations off.
driver.o: driver.cpp comparisons.h
$(CC) -c -o driver.o -std=c++11 -O0 driver.cpp
# Compile the code being tested separately with optimizations on.
comparisons.o: comparisons.cpp comparisons.h
$(CC) -c -o comparisons.o -std=c++11 -O3 comparisons.cpp
clean:
rm comparisons.o driver.o test
在this answer 的建议下,我在一个单独的编译单元中编译了我的比较函数并进行了优化,并在关闭优化的情况下编译了驱动程序,但我仍然会减慢大约 5 倍。
strcmp - 154519
strcmp_custom - 506282
我也尝试复制FreeBSD implementation,但得到了类似的结果。
我想知道我的绩效衡量是否忽略了某些东西。还是标准库的实现做得更好?
【问题讨论】:
-
我认为stdlib在汇编中实现了这个功能,可能使用了一些与汇编相关的技巧(虽然我不能给出任何例子)。
-
如果库实现的性能与原版实现一样差,我会认为它已损坏。
-
我认为使用 SSE 内在函数可以实现类似的性能,而不必求助于 asm。通常使用 asm 来挤出最后 10-20% 的性能。
-
在更高的优化级别中,一些基本函数(如 memcpy)甚至没有从库中链接,而是替换为编译器内部版本,如果您想防止 gcc 出现这种行为,请尝试
-fno-builtin
标签: c++ string performance