-1

我有一个关于复制以 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++;
}

两种方式都是真实的和成功的。现在我想检查 1000 万次并为 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 毫秒

4

3 回答 3

4

用自己的函数替换库函数通常会导致性能下降。

memcpy代表一个非常基本的内存操作。因此,它的作者对其进行了高度优化。与“幼稚”的实现不同,库版本尽可能一次移动多个字节,并在可用的平台上使用硬件辅助。

此外,编译器本身“知道”memcpy其他库函数的内部工作原理,并且对于在编译时已知长度的情况,它可以完全优化它们。

注意:您的实现具有 的语义strcpy,而不是memcpy

于 2017-07-16T10:48:06.697 回答
1

...这两种方式都是一样的!

不,他们不是:

  1. memcpy()不检查每个字符是否包含'\0'
  2. 实施者所做的优化可能比您在幼稚的方法中所做的更多

您的方法不太可能比memcpy().

于 2017-07-16T10:46:57.457 回答
0

看到你没有使用指针并将你正在做的事情(strcpy)与 memcpy 进行比较清楚地表明你是一个初学者,正如其他人已经说过的那样,很难超越像那些为你的库编写代码的经验丰富的程序员。

但我会给你一些提示来优化你的代码。我快速浏览了 Microsoft 的 C 标准库实现(称为 C 运行时库),他们在汇编中执行它比在 C 中执行它要快。所以这是速度的一点。

在大多数带有 32 位总线的 32 位架构中,CPU 可以在一次请求内存中从内存中获取 32 位信息(假设数据正确对齐),但是即使您需要 16 位或 8 位,它仍然需要提出 1 个请求。因此,使用机器的字长可能会加快速度。

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

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

于 2017-07-16T21:12:16.607 回答