【问题标题】:performance is degraded with -m64 flag使用 -m64 标志会降低性能
【发布时间】:2015-02-02 10:39:23
【问题描述】:

我编写了一个简单的过滤器程序来查看使用-m64 编译器选项是否比-m32 有性能改进。

这是我的全部代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include<sys/time.h>
#define __STDC_FORMAT_MACROS 1
#include<inttypes.h>

#define tap_size 5
int luma_stride=640;
int luma_ht=480;
int croma_stride=320;
int croma_ht=240;

int filter[tap_size]={-3,2,3,2,-3};


struct timeval tv1, tv2,tv3;
uint64_t  ui1;
uint64_t total_time=0;

uint64_t GetTimeStamp();
void process_frame(unsigned char *ip_buffer, unsigned char * op_buffer, int ip_buf_size, int op_buf_size);


int main()
{

    int ip_buf_size;
    int op_buf_size;


    unsigned char * ip_buffer;
    unsigned char * op_buffer;
    unsigned char * temp;



    ip_buf_size=luma_stride*luma_ht + 2*croma_stride * croma_ht;
    op_buf_size=ip_buf_size; //

    ip_buffer = (unsigned char *)malloc(ip_buf_size*sizeof(char));
    op_buffer = (unsigned char *)malloc(ip_buf_size*sizeof(char));;
    temp=ip_buffer;
    for(int i=0;i<ip_buf_size;i++)
    {
        *temp=rand();
    }

    for(int i=0;i<100;i++)
    {
        ui1=GetTimeStamp();
        process_frame(ip_buffer, op_buffer, ip_buf_size, op_buf_size);//process
        total_time+=GetTimeStamp()-ui1;
    }
    free(ip_buffer);
    free(op_buffer);
    printf("\nTotal time=%" PRIu64 " us\n", total_time);
    return 0;
}



uint64_t GetTimeStamp()
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return tv.tv_sec*(uint64_t)1000000+tv.tv_usec;
}


void process_frame(unsigned char *ip_buffer, unsigned char * op_buffer, int ip_buf_size, int op_buf_size)
{

    int i,j;
    unsigned char *ptr1,*ptr2;
    unsigned char *temp_buffer=(unsigned char *) malloc(op_buf_size*sizeof(unsigned char));

    ptr1=ip_buffer;
    //ptr2=temp_buffer;
    ptr2=op_buffer;


    //Vertical filter

    //Luma
    /*  for(j=0;j<tap_size/2;j++)
     {
     for(i=0;i<luma_stride;i++)
     {
     *ptr2++=*ptr1++;
     }
     } */

    memcpy(ptr2,ptr1,2*luma_stride*sizeof(unsigned char));
    ptr1=ip_buffer+2*luma_stride;
    ptr2=op_buffer+2*luma_stride;

    for(i=0;i<luma_ht-tap_size+1;i++)
    {

        for(j=0;j<luma_stride;j++)
        {
            int k;
            long int temp=0;
            for(k=0;k<tap_size;k++)
            {
                temp+=filter[k]**(ptr1+(k-tap_size/2)*luma_stride);
            }
            //temp=temp>>4;
            if(temp>255) temp =255;
            else if(temp<0) temp=0;
            *ptr2=temp;
            ++ptr1;
            ++ptr2;
        }

    }

    memcpy(ptr2,ptr1,2*luma_stride*sizeof(unsigned char));
    ptr1=ptr1+2*luma_stride;
    ptr2=ptr2+2*luma_stride;

    //Copy croma values as it is!
    for(i=luma_ht*luma_stride;i<ip_buf_size;i++)
    {
        op_buffer[i]=ip_buffer[i];
    }
}

我用这两个选项编译它

g++ -O3 program.c -o filter64 -m64

g++ -O3 program.c -o filter32 -m32

现在,

./filter32 的输出是

Total time=106807 us

./filter64的那个是

Total time=140699 us

我的问题是不应该是其他方式吗?即 filter64 所花费的时间应该少于 filter32 所花费的时间,因为使用 64 位架构我们有更多的寄存器?我怎样才能做到这一点?或者是否有任何编译器选项可以解决这个问题? 请帮忙。

我在英特尔 64 位机器上使用 ubuntu。

【问题讨论】:

  • 如果只测量时间,在 for 循环之前和之后(而不是 for 内的 100 次),结果是否相同?如果将重复次数从 100 增加到例如 100000,结果是否相同?
  • 大量使用指针的代码可能会降低性能,因为现在可以放入缓存的指针减少了。您还应该内联 GetTimeStamp 并尽可能使用更高精度的计时器。另一个解决方案是-mx32

标签: c performance compiler-optimization


【解决方案1】:

当您从 32 位切换到 64 位时,需要进行各种权衡。不利的一面是,所有指针都变成两倍大小,并且可能需要更长的指令序列才能将立即地址加载到寄存器中。除非您的应用程序寄存器不足或需要 > 4 GB 的地址空间,否则您可能希望将其保持为 32 位。

还请注意,您的计时方法有些可疑 - 您可能只是看到了页面错误等的影响 - 您应该将测试代码放入循环中,在循环外分配内存,在循环内分配处理代码。出于计时目的忽略第一次迭代。这样,所有内存都已连接,并且缓存在开始计时之前已预热。

还有一个问题:process_frame 中似乎存在内存泄漏,这不仅是一个错误,还可能导致计时不可靠。

【讨论】:

  • 更改了代码以适应您的所有建议,但没有运气:( `process_frame(ip_buffer, op_buffer, ip_buf_size, op_buf_size);//process ui1=GetTimeStamp(); for(i=0;i
  • 您是否将mallocs/frees 移出process_frame() 或者它们仍在循环中?实际上,我看到您现在正在 process_frame() 内部泄漏内存,所以这无济于事...
  • malloc 和 free 在 main 函数的循环之外。所以没有任何内存泄漏的机会。
  • 仔细看 - 你是 malloc-ing 一个临时缓冲区 (temp_buffer) 在 process_frame() 里面你从来没有 free (实际上看起来你甚至从未使用它?)。
【解决方案2】:

为什么要使用 C++ 编译器来编译 C?这会让你的 C 代码变得更糟,因为你必须做一些可怕的事情,比如不得不cast the return value of malloc() 等等。

另外,您确定您的程序的性能受到可用寄存器的限制吗?您需要对您的程序进行概要分析,以准确了解时间花在何处,以了解迁移到 64 位是否/如何使其更快。

这并不像“为 64 位构建时所有代码都更快,因为有更多寄存器”那么简单。

【讨论】:

  • 使用 C 编译器 (gcc) 进行编译,结果相似。我期望从 32 切换到 64 时至少不会出现降级。我会按照您的建议进行分析并让您知道。
猜你喜欢
  • 2012-06-22
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 2020-12-21
  • 2015-07-01
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多