如何降低CPU使用率?

时间:2012-02-15 07:04:19

标签: c++ performance cpu-usage

我必须解码一些字节数组(原始数据)。它可以包含基本数据类型(int,unsigned int,char,short等)。根据定义的结构,我需要解释它们。以下是例子:

struct testData
{ 
 int a;
char c;
};
   unsigned char** buf = {0x01,0x00,0x00,0x00,0x41}
   example byte array(in little endian) : 0100000041

   should give decoding like : a = 1, c = 'A'

样本数据可能非常大,样本结构(例如testData)可以包含200-3000个字段。 如果我使用am cast从** buf中读取相应的数据并设置如下所示的指针:

    int a = *(reinterpret_cast<int*>(*buf);
    *buf += 4;
    char c = **buf;
    *buf += 1;

如果需要解码的文件数很高,我的CPU使用率会很高。例如:

    struct testData
    {
     int element1;
     char element2;
     int element3;
      ... ...
     ... ...
      short element200;
     char element201;
     char element202;
    }

有没有办法减少CPU负载并保持解码速度非常快?

我有两个限制:

  1. &#34;结构可以包含填充字节。&#34;
  2. 我无法控制如何定义结构。结构也可以包含嵌套元素。

3 个答案:

答案 0 :(得分:5)

int a = *(reinterpret_cast<int*>(*buf);

请勿使用reinterpret_cast。您在骗编译器并强制进行未对齐访问。更糟糕的是,您正在从编译器中隐藏以优化代码所需的信息 - 指针实际上是字符。相反,将您的意思编码为尽可能简单,即:

int a=static_cast<int>(*buf[0]) |
     (static_cast<int>(*buf[1])<<8) |
     (static_cast<int>(*buf[2])<<16) |
     (static_cast<int>(*buf[3])<<24);

这很简单,清晰,你真正想要的是什么。编译器在优化它时没有问题。 (并且,无论您的平台的字节顺序如何,它都能正常工作。)

答案 1 :(得分:2)

只要结构正确打包,您应该能够简单地将结构映射到缓冲区:

#pragma pack(push, 1)
struct testData
    {
     int element1;
     char element2;
     int element3;
      ... ...
     ... ...
      short element200;
     char element201;
     char element202;
    }
#pragma pack(pop)

您还应该以对齐的方式声明结构,不要混合int后跟char后跟int ...然后如果您读取数据对齐缓冲区,缓冲区到testData*的简单转换将允许您访问所有成员。这样你就可以避免所有那些无偿的副本。如果您以正向方式阅读结构(p->element1,然后阅读p->element2,然后阅读p->element3,依此类推)hardware prefetch应该启动并大力提升。

进一步的改进需要对热点进行实际测量。另外,请从图书馆查看本书并阅读:The Software Optimization Cookbook

答案 2 :(得分:1)

除了David Schwartz的回复之外,你可以通过编写一些帮助模板函数来整理它。我建议这样的事情(未经测试)。

template<typename T>
const unsigned char * read_from_buffer( T* value, const unsigned char * buffer);

template<>
const unsigned char * read_from_buffer<int>( int* value, const unsigned char * buffer)
{
   *value = static_cast<int>(*buf[0]) |
     (static_cast<int>(*buf[1])<<8) |
     (static_cast<int>(*buf[2])<<16) |
     (static_cast<int>(*buf[3])<<24);
   return buffer+4'
}

template<>
const unsigned char * read_from_buffer<char>( char * value, const unsigned char * buffer )
{
  *value = *buffer;
  return buffer+1;
}

struct TestData
{
  int a;
  char c;
};

int main()
{
  unsigned char buf[] = {0x01,0x00,0x00,0x00,0x41};
  unsigned char * ptr = buf;

  TestData data;
  ptr = read_from_buffer( &data.a, ptr );
  ptr = read_from_buffer( &data.c, ptr );
}

您可以进一步封装它并添加错误检查等,并且您有一个很好的二进制流,如接口。