2017-07-16 64 views
-1

我有一个关于复制一个0结尾的字符串的问题:更快的方式比的memcpy复制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 milions倍和的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速度快,也许速度更快)? 我如何更新我自己的方式(while)使其更快或与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毫秒

+2

你如何衡量执行时间? –

+3

依靠数组末尾的“\ 0”字符,与“memcpy()”不同。如果你想处理这种情况,那么只有你用'strcpy()'才可能比使用自己的函数更好(实现中可能会使用某些技巧,使得它比实现更快)。 – user0042

+3

为什么你认为你可以智取编译器标准库的创建者? – PaulMcKenzie

回答

1

...这两方面的方法是一样的!

不,他们不是:

  1. memcpy()不检查每个字符包含'\0'与否。
  2. 可能有更多的优化,由实施者做得比你在天真方法有

这是不可能的,你的方法可以比memcpy()更快。

+1

请删除您的答案,并将其作为评论发布。 –

+2

@ Khaled.K为什么这样?我的回答很好地解释了差异。 – user0042

+0

那么memcpy如何创建一个从str到temp的副本? – myOwnWays

3

用自己的代替库函数往往导致性能低下。

memcpy代表一个非常基本的记忆操作。因此,它的作者进行了高度优化。与“天真”实现不同,只要有可能,库版本就会一次移动多个字节,并在可用的平台上使用硬件协助。此外,编译器本身“知道”memcpy和其他库函数的内部工作方式,并且可以在编译时知道长度的情况下完全优化它们。

注:你的实现具有strcpy,不memcpy语义。

+0

好的,我想知道如何! 100%的memcpy也检查每个字符! (逐一复制...),为什么它必须更快! – myOwnWays

+1

@myOwnWays阅读库实现源代码和/或在发布(优化)构建中检查生成的汇编器。 –

+3

@myOwnWays _“memcpy检查每个字符!”_咦?不,它没有。 – user0042

0

看到你没有使用指针,并将你正在做的事(strcpy)与memcpy进行比较清楚地表明你是初学者,而且正如其他人已经指出的那样,你很难胜任一个像编码图书馆。

但我会给你一些提示来优化你的代码。 我简要介绍了Microsoft的C标准库实现(称为C运行时库),并且它们在组装中执行速度比在C中快。所以这是速度的一个要点。在大多数具有32位总线的32位体系结构中,CPU可以在一个请求中从内存中获取32位信息到内存(假设数据正确对齐),但即使您需要16位或8位,它仍然需要提出这1个请求。所以使用你的机器的字大小可能会给你一些加速。

最后,我想把你的注意力引向SIMD。如果你的CPU提供它,你可以使用它并获得额外的速度。 MSCRT也有一些SSE2优化选项。

在过去,我不得不编写优于我的库实现的代码,因为我有一个特定的需求或特定类型的数据,我可以优化它,但它可能具有一些教育价值,除非专门所需时间最好花在实际代码上,而不是花在重新实现库函数上。

相关问题