首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >低水平C/C++性能?

低水平C/C++性能?
EN

Stack Overflow用户
提问于 2014-02-27 15:24:03
回答 5查看 465关注 0票数 5

更新:我刚刚成功地击败了我自己的32 if代码:

代码语言:javascript
复制
void test(char *file_char, unsigned int size)
{
    char* file_ = file_char;
    char* size_x = file_char+size;
    char to_find = 0;

    for(unsigned int i = 0; i < 10000; i++)
    {
        file_char = file_;

        while(*file_char++ != to_find);//skip all characters till we find a 0

        if(*file_char)//some if in order to avoid compiler removing our test code
            cout << "found";
    }
}

上面的代码要求0至少在数组中出现一次,否则会出现错误,但它比if代码要快一些,而且要紧凑得多。

有什么办法使上面的代码更快吗?(有一个char数组并试图找到char出现的位置)?

我写了一些代码,我真的很困惑。

init:

代码语言:javascript
复制
int main()
{
    FILE *file;
    file = fopen("C:\\data.txt", "rb");

    static const int size = 60000;

    char *file_char = (char*)malloc(size);

    unsigned int i = 0;
    while(i < size)
        fread(&file_char[i++], 1, 1, file);

    clock_t clock_ = clock();
    test(file_char, size);
    std::cout << ((double)clock()-clock_)/1000;
    return 0;
}

下面的代码需要3.5秒才能执行:

代码语言:javascript
复制
void test(char *file_char, unsigned int size)
{
    for(unsigned int i = 0; i < 100000; i++)
    {
        unsigned int pos = 0;
        char to_find = 0;
        while(pos < size)
            if(file_char[pos++] == to_find)
                std::cout << "found";
    }
}

但是下面的代码需要1.8秒,一半的时间!

代码语言:javascript
复制
void test(char *file_char, unsigned int size)
{
    for(unsigned int i = 0; i < 100000; i++)
    {
        unsigned int pos = 0;
        char to_find = 0;
        while(pos < size)
        {
            if(file_char[pos] == to_find)
                std::cout << "found";
            else if(file_char[pos+1] == to_find)
                std::cout << "found";
            else if(file_char[pos+2] == to_find)
                std::cout << "found";
            else if(file_char[pos+3] == to_find)
                std::cout << "found";
            else if(file_char[pos+4] == to_find)
                std::cout << "found";
            else if(file_char[pos+5] == to_find)
                std::cout << "found";
            else if(file_char[pos+6] == to_find)
                std::cout << "found";
            else if(file_char[pos+7] == to_find)
                std::cout << "found";
            else if(file_char[pos+8] == to_find)
                std::cout << "found";
            else if(file_char[pos+9] == to_find)
                std::cout << "found";
            else if(file_char[pos+10] == to_find)
                std::cout << "found";
            else if(file_char[pos+11] == to_find)
                std::cout << "found";
            else if(file_char[pos+12] == to_find)
                std::cout << "found";
            else if(file_char[pos+13] == to_find)
                std::cout << "found";
            else if(file_char[pos+14] == to_find)
                std::cout << "found";
            else if(file_char[pos+15] == to_find)
                std::cout << "found";
            else if(file_char[pos+16] == to_find)
                std::cout << "found";
            else if(file_char[pos+17] == to_find)
                std::cout << "found";
            else if(file_char[pos+18] == to_find)
                std::cout << "found";
            else if(file_char[pos+19] == to_find)
                std::cout << "found";
            else if(file_char[pos+20] == to_find)
                std::cout << "found";
            else if(file_char[pos+21] == to_find)
                std::cout << "found";
            else if(file_char[pos+22] == to_find)
                std::cout << "found";
            else if(file_char[pos+23] == to_find)
                std::cout << "found";
            else if(file_char[pos+24] == to_find)
                std::cout << "found";
            else if(file_char[pos+25] == to_find)
                std::cout << "found";
            else if(file_char[pos+26] == to_find)
                std::cout << "found";
            else if(file_char[pos+27] == to_find)
                std::cout << "found";
            else if(file_char[pos+28] == to_find)
                std::cout << "found";
            else if(file_char[pos+29] == to_find)
                std::cout << "found";
            else if(file_char[pos+30] == to_find)
                std::cout << "found";
            else if(file_char[pos+31] == to_find)
                std::cout << "found";

            pos+=32;
        }
    }
}

我使用的是Visual 2012 x64,程序永远不会删掉任何东西,因为没有字符是0。这怎么解释呢?如何在不使用32个ifs的情况下存档相同的性能?

编辑1:如果我创建了64个ifs,那么在32个ifs版本上没有速度增长。

编辑2:,如果我移除else并离开如果程序需要4秒。

现在,如何解释上述不合理的结果呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-02-27 16:32:38

我做了一些测试只是为了确定。

对于g++ (在Linux和Windows下),我有与Visual相同的结果:

版本1(没有显式循环展开)

g++ -O3 7.5s

第2版(显式循环展开)

g++ -O3 2.1 s

但是,在打开-funroll-loops选项(通常默认情况下不启用此优化,因为它可能或不可能使其运行得更快):

版本1(没有显式循环展开)

g++ -O3 -funroll-loops 2.2 s

第2版(显式循环展开)

g++ -O3 -funroll-loops 2.2 s

这与循环展开有关。

编辑

您可以将最后一个示例更改为显式插入哨兵,如下所示:

代码语言:javascript
复制
int main()
{
  static const int size = 60000;

  char *file_char = (char*)malloc(size+1);  // The last element is the sentry

  // ...Fill file_char[]...

  file_char[size] = 0;  // the sentry

  // ...
}

因此,test函数不会失败(当然,您必须检查是否找到哨兵或“好”零,但它只是一个如果)。

第3版(哨兵)

g++ -O3 0.68s

g++ -O3 -funroll-loops 0.72s

票数 4
EN

Stack Overflow用户

发布于 2014-02-27 15:26:58

您的循环主要由两个比较组成:pos < sizefile_char[pos] == to_find。通过展开循环,您可以将比较的数量从2* size减少到(size + size / 32)。

票数 9
EN

Stack Overflow用户

发布于 2014-02-27 15:34:13

我认为这两种密码是不同的。

在第一个例子中,您每次都会检查“if”比较。

在第二个,如果第一个是好的,你跳过以下所有的!(因为其他原因)所以你保存了大量的比较(但缺少检查)。

为了具有相同的代码,您必须删除所有的“delete”。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22072858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档