【问题标题】:How to reduce CPU usage?如何降低 CPU 使用率?
【发布时间】:2012-02-15 07:04:18
【问题描述】:

我必须解码一些字节数组(原始数据)。它可以包含基本数据类型(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 个字段。 如果我使用强制转换从 **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. “结构可以包含填充字节。”
  2. 我无法控制如何定义结构。结构也可以包含嵌套元素。

【问题讨论】:

    标签: c++ performance cpu-usage


    【解决方案1】:
    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);
    

    这很简单,很清楚,是您真正想要的。编译器优化它没有问题。 (而且,无论您平台的字节序如何,它都可以正常工作。)

    【讨论】:

    • 是不是逐字节读取和移位操作会比使用强制转换读取多个字节慢?
    • @learningstack 也许,也许不是。这可能取决于平台。但我不必担心,因为我使用了好的编译器,而且我不会对他们撒谎。演员向编译器谎报对齐并欺骗它生成错误代码。
    【解决方案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-&gt;element1,然后阅读p-&gt;element2,然后阅读p-&gt;element3 等等)hardware prefetch 应该会发挥作用并给予很大的推动。

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

    【讨论】:

    • 非常感谢您的评论。但我有两个限制:
    • 非常感谢您的评论。但我有两个限制:1.“结构可以包含填充字节。” 2. 我无法控制如何定义结构。结构也可以包含复合元素(结构、联合、数组等)。
    【解决方案3】:

    根据 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 );
    }
    

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

    【讨论】:

    • 是不是逐字节读取和移位操作会比使用强制转换读取多个字节慢?
    猜你喜欢
    • 2023-03-27
    • 2016-06-11
    • 1970-01-01
    • 2023-04-03
    • 2023-01-03
    • 2012-11-16
    • 2018-12-13
    • 2023-03-18
    • 2015-11-01
    相关资源
    最近更新 更多