【问题标题】:Generic wrappers for templates: optimization opportunities模板的通用包装器:优化机会
【发布时间】:2012-08-12 07:27:29
【问题描述】:

我正在尝试将模板与泛型结合起来,重点是尽可能快地(合理地)访问原始/值类型的属性,最好将其保留在 C++/CLR 中。考虑这个简单的模板:

template< typename type >
class value_wrapper {
public:
    type value;
};

及其对应物:

generic< typename T >
public ref class ValueWrapper {
    ...
public:
    property T Value {
        T get() {
            if( T::typeid == System::Int32::typeid )
                return ( T )( ( value_wrapper< int > * )ptr )->value;
            ...branches for some other types...
            // if all else fails:
            return ( T )( Object ^ )( ( value_wrapper< gcroot< Object ^ > > * )ptr )->value;
        }
        ...
    }
    ...
private:
    void *ptr;
};

问题 1. 当泛型的 MSIL 转换为值类型的特化时,代码是否进一步优化?是否可以在这里检查类型,例如,在ValueWrapper&lt;int&gt; 分支中的非 int 类型和类型比较本身将被优化掉?

现在,在每个方法中列出所有支持的类型有点痛苦,所以我为此制作了一个单独的函数:

template< typename action, typename context_type >
__forceinline
static bool apply( System::Type ^type, void *value, System::Object ^*box, context_type context ) {
    if( type == System::Int32::typeid )
        return action().operator()< int >( ( int * )value, context ), true;
    ...branches for some other types...
    // if all else fails:
    return action().operator()< gcroot< System::Object ^ > >( box, context ), false;
}

struct get_value {
    template< typename type, typename result_type >
    void operator () ( result_type *result, void *ptr ) {
        *result = ( ( value_wrapper< type > * )ptr )->value;
    }
};

generic< typename T >
public ref class ValueWrapper {
    ...
    property T Value {
        T get() {
            T result;
            System::Object ^box;
            return apply< get_value >( T::typeid, &result, &box, ptr ) ? result : ( T )box;
        }
        ...
    }
    ...
};

事实证明,这比原始代码慢了大约 3 倍。

问题 2。 此处可以进行哪些更改以允许优化器使第二个实现在速度上更接近第一个(理想情况下,速度差异在 10%-20% 之内)? p>

附:这主要是关于 VC 2010。但如果 VC 2012 在这方面有所不同,那也很高兴。

【问题讨论】:

  • 使用case 可能会加快速度。第二个实现速度较慢,并且可能不如第一个实现快,因为您首先构造一个T,然后分配给它。此外,您将System::Object^ 放在堆栈上,即使并非在所有情况下都需要它,并且函数调用可能会有一些开销。
  • @stijn 你的意思是switch( T::typeid )?我不认为这是可能的。至于第二个问题,我可以接受 10%-20% 的速度差异,而不是 3 倍。为清晰起见进行编辑。 (另外:理论上,内联可以帮助减少函数调用开销,并检测 box 的不必要性并删除它,并摆脱对 result 的额外操作。这完全取决于优化器的能力。)
  • 哎呀,抱歉确实打开 typeid 不起作用

标签: c++ templates generics optimization c++-cli


【解决方案1】:

经过一些修补和 MSIL 观察后,我对第二个问题有了答案:只需传递一个 typeid getter 函数而不是 typeid 本身。框架在每次比较时请求类型信息似乎比将其存储到某个变量(旧的type 参数)中并重用它要容易得多。

使用这种方法,减速从 3 倍下降到大约 5-10% (!)。

问题 2 结束,问题 1 待定。

生成的代码:

template< typename action, typename context_type >
__forceinline
static bool apply( System::Type ^type(), void *value, System::Object ^*box, context_type context ) {
    if( type() == System::Int32::typeid )
        return action().operator()< int >( ( int * )value, context ), true;
    if( type() == SupportedStruct::typeid )
        return action().operator()< SupportedStruct >( ( SupportedStruct * )value, context ), true;
    if( type() == System::String::typeid )
        return action().operator()< std::wstring >( ( System::String ^* )value, context ), true;
    // for both reference types and unknown value types:
    return action().operator()< gcroot< System::Object ^ > >( box, context ), false;
}

struct get_value {
    template< typename type, typename result_type >
    void operator () ( result_type *result, void *ptr ) {
        *result = ( ( value_wrapper< type > * )ptr )->value;
    }
    template< typename type >
    void operator () ( System::String ^*result, void *ptr ) {
        *result = gcnew System::String( ( ( value_wrapper< type > * )ptr )->value.c_str() );
    }
};

generic< typename T >
public ref class ValueWrapper {
    ...
public:
    property T Value {
        T get() {
            T result;
            System::Object ^box;
            return apply< get_value >( TypeGetter, &result, &box, ptr ) ? result : ( T )box;
        }
        ...
    }
    ...
private:
    void *ptr;
private:
    static System::Type ^TypeGetter() {
        return T::typeid;
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多