使用 -m64 标志会降低性能
performance is degraded with -m64 flag
我写了一个简单的过滤器程序,看看 -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 位架构中我们有更多的寄存器?我怎样才能做到这一点?还是有任何编译器选项可以解决这个问题?
请帮忙。
我在 intel 64 位机器上使用 ubuntu。
为什么要使用 C++ 编译器来编译 C?它会让你的 C 代码变得更糟,因为你必须做一些可怕的事情,比如必须 cast the return value of malloc()
等等。
此外,您确定您的程序的性能受到可用寄存器的限制吗?您需要对您的程序进行概要分析以弄清楚时间花在了哪里,弄清楚 if/how 迁移到 64 位可以使它更快。
不像"all code is faster when built for for 64-bit, because there are more registers"那么简单。
从 32 位切换到 64 位时需要进行各种权衡。不利的一面是,所有指针的大小都变成了两倍,并且可能需要更长的指令序列才能将立即地址加载到寄存器中。除非您的应用程序寄存器不足或需要 > 4 GB 地址 space,否则您可能希望将其保留为 32 位。
另请注意,您的计时方法有些可疑 - 您可能只是看到页面错误等的影响 - 您应该将测试代码放入循环中,在循环外分配内存,在循环内处理代码.出于计时目的忽略第一次迭代。这样所有内存都已连线并且缓存在开始计时之前已预热。
另一个问题:您似乎在 process_frame
中有内存泄漏,这不仅是一个错误,还可能使计时不可靠。
我写了一个简单的过滤器程序,看看 -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 位架构中我们有更多的寄存器?我怎样才能做到这一点?还是有任何编译器选项可以解决这个问题? 请帮忙。
我在 intel 64 位机器上使用 ubuntu。
为什么要使用 C++ 编译器来编译 C?它会让你的 C 代码变得更糟,因为你必须做一些可怕的事情,比如必须 cast the return value of malloc()
等等。
此外,您确定您的程序的性能受到可用寄存器的限制吗?您需要对您的程序进行概要分析以弄清楚时间花在了哪里,弄清楚 if/how 迁移到 64 位可以使它更快。
不像"all code is faster when built for for 64-bit, because there are more registers"那么简单。
从 32 位切换到 64 位时需要进行各种权衡。不利的一面是,所有指针的大小都变成了两倍,并且可能需要更长的指令序列才能将立即地址加载到寄存器中。除非您的应用程序寄存器不足或需要 > 4 GB 地址 space,否则您可能希望将其保留为 32 位。
另请注意,您的计时方法有些可疑 - 您可能只是看到页面错误等的影响 - 您应该将测试代码放入循环中,在循环外分配内存,在循环内处理代码.出于计时目的忽略第一次迭代。这样所有内存都已连线并且缓存在开始计时之前已预热。
另一个问题:您似乎在 process_frame
中有内存泄漏,这不仅是一个错误,还可能使计时不可靠。