我有一个关于复制以0结尾的字符串的问题:
const char * str = "Hello World !";
size_t getSize = strlen(str);
char * temp = new char[getSize + 1];
...我知道我可以使用这个功能
memcpy(temp, str, getSize);
但我想使用我自己的复制功能,其功能如下
int Count = 0;
while (str[Count] != '\0') {
temp[Count] = str[Count];
Count++;
}
这两种方式都是真实而成功的。现在我想以10百万次检查它,并为memcpy做这个动作
const char * str = "Hello World !";
size_t getSize = strlen(str);
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
memcpy(temp, str, getSize);
}
这是我自己的方式
const char * str = "Hello World !";
size_t getSize = strlen(str);
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
int Count = 0;
while (str[Count] != '\0') {
temp[Count] = str[Count];
Count++;
}
}
第一个过程在 420毫秒完成,第二个过程在 650毫秒完成 ......为什么?这两种方式都是一样的!我想使用自己的功能而不是memcpy。有没有办法让自己的方式更快(快速,因为memcpy快或可能更快)? 如何更新自己的方式(同时)使其更快或与memcpy相等?
完整的来源
int main() {
const char * str = "Hello world !";
size_t getSize = strlen(str);
auto start_t = chrono::high_resolution_clock::now();
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
memcpy(temp, str, getSize);
}
cout << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_t).count() << " milliseconds\n";
start_t = chrono::high_resolution_clock::now();
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
int done = 0;
while (str[done] != '\0') {
temp[done] = str[done];
done++;
}
}
cout << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_t).count() << " milliseconds\n";
return 0;
}
结果:
482毫秒
654毫秒
答案 0 :(得分:3)
用您自己的库替换库函数通常会导致性能下降。
memcpy
表示非常基本的内存操作。因此,它的作者高度优化。与“天真”实现不同,只要有可能,库版本就会一次移动多个字节,并在可用的平台上使用硬件辅助。
此外,编译器本身“知道”memcpy
和其他库函数的内部工作方式,并且可以在编译时知道长度的情况下完全优化它们。
注意:您的实现的语义为strcpy
,而不是memcpy
。
答案 1 :(得分:1)
......这两种方式都是一样的!
不,他们不是:
memcpy()
不会检查每个字符是否包含'\0'
。您的方法不可能比memcpy()
更快。
答案 2 :(得分:0)
看到你没有使用指针并将你正在做的事情(strcpy)与memcpy进行比较,清楚地表明你是一个初学者,而且正如其他人已经说过的那样,很难超过一个有经验的程序员,比如编写你的库的人
但我会给你一些提示来优化你的代码。 我快速浏览了一下微软的C标准库实现(被称为C运行时库),他们在汇编中这样做比在C中做得快。所以这是速度的一点。
在大多数具有32位总线的32位架构中,CPU可以在一次请求中从内存中获取32位信息(假设数据已正确对齐),但即使您需要16位或8位,它仍然需要提出1个请求。因此,使用机器的字大小可能会让您加快速度。
最后,我想引导您注意SIMD。如果您的CPU提供它,您可以使用它并获得额外的速度。 MSCRT再次提供了一些SSE2优化选项。
在过去,我不得不编写优于我的库实现的代码,因为我有一个特定需求或特定类型的数据,我可以优化,虽然它可能具有一定的教育价值,除非特别需要,花在重新实现库函数上的时间最好花在实际代码上。