【问题标题】:Small Buffer Optimization and alignment小缓冲区优化和对齐
【发布时间】:2012-10-25 20:53:04
【问题描述】:

我正在围绕旧版 API 编写 C++ 包装器。这个API为我提供了一个指针值来保存额外的数据,我想用它来实现Small Buffer Optimization

我已经实现了一个is_small_pod 元函数,它检查给定类型是否是POD并且它是否适合void*

template< typename Type >
struct is_small_pod
  : std::integral_constant<
        bool
      , std::is_pod< Type >::type::value
        && sizeof( Type ) <= sizeof( void* )
    >
{};

我正在设置这样的值:

// void*& param;
if( detail::is_small_pod< Type >() )
{
    *static_cast< Type* >( &param ) = value;
} else {
    param = new Type( value );
}

我是否正确实施了这种优化?我相信当值对齐与指针的 alignment 不兼容时,这将失败(可能是奇怪的极端情况)。这种情况甚至可能,还是我只是想多了?我应该如何扩展我的 metafunction 以检查兼容的 alignment

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    类型的对齐方式不可能大于该类型的大小。

    3.11 对齐[basic.align]

    [...] alignment 是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。

    5.3.3 Sizeof [expr.sizeof]

    2 - [...] n 个元素的数组的大小是元素大小的 n 倍。

    因此,您的代码只有在 alignof(void *) &lt; sizeof(void *) 时才会中断,而在大多数平台上并非如此。

    为了安全,你可以这样写:

    template< typename Type >
    struct is_small_pod
      : std::integral_constant<
            bool
          , std::is_pod< Type >::type::value
            && sizeof( Type ) <= sizeof( void* )
            && alignof( Type ) <= alignof( void* )
        >
    {};
    

    【讨论】:

    • 虽然在技术上是正确的,但这确实忽略了日常事务,例如 SSE* 支持的 16 字节对齐要求。
    • @ildjarn 对于 SSE,您通常倾向于使用 __m128 等,其大小为 16 字节且对齐。
    【解决方案2】:

    作为一种通用方法,您始终可以尝试测试您的理论。我想你会做这样的事情:

    template< class Type >
    bool TestAlignmentSanity( Type value )
    {
        // This function is only valid for small POD types
        if( !detail::is_small_pod< Type >() )
            return false;
    
        // Temporary space covering alignments spanning the size of a void*
        const int nBytes = sizeof(void*);
        char buffer[sizeof(Type) + nBytes - 1];
    
        // For each target alignment, test that a copy is successful.
        for( int i = 0; i < nBytes; i++ )
        {
           Type * target = static_cast< Type* >( &buffer[i] );
    
           // Sanity-check that the pointer was actually aligned as we requested
           if( (char*)target != &buffer[i] ) return false;
    
           // Copy and test that the result is as expected.  Assumes '==' operator
           // is defined...  Otherwise, implement with byte comparisons.
           *target = value;
           if( !(*target == value) ) return false;
        }
    
        return true;
    }
    

    在这里我测试了可以将数据类型复制到跨越void* 大小的任何对齐方式中。这只是一个想法。 =)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 2020-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多