2

テンプレート化された GPGPU tensor sum 関数を作成しています (主に楽しみのためですが、テンプレートのメタプログラミングと GPGPU プログラミングの理解を深めるためにも)、関数の無効な使用を防ぐためにいくつかの静的アサーションを実行したいと考えています。

C++ AMParray_viewクラスの要件の 1 つは、それが長方形であることです (つまり、すべての範囲が同じです)。

ただし、これを行う方法が完全にはわかりません。現在、私の関数は次のようになります。

template <typename T, typename U>
auto TensorSum( T t, U u )->decltype( std::remove_all_extents<T>::type + std::remove_all_extents<U>::type )
{
    using SumType = decltype(std::remove_all_extents<T>::type + std::remove_all_extents<U>::type);

    static_assert( std::rank<T>::value == std::rank<U>::value, "The two tensors must have the same rank" );

    // ToDo: Put a static assertion here to ensure tensors are rectangular

    SumType arrSum[std::rank<T>::value * std::extent<U>::value];

    concurrency::array_view<std::remove_all_extents<T>::type, std::rank<T>::value> a( std::extent<T>::value, t );
}

私の主な問題は、ランクが変数であり、コンパイル時に反復を実行する方法がないことです。

4

2 に答える 2

0

次のboost::mplコードは、あなたが求めることを行います。
重要なのは、ループを累積と呼び出しに再定式化することboost::mpl::foldです。

    #include <boost/mpl/range_c.hpp>
    #include <boost/mpl/fold.hpp>
    #include <boost/mpl/int.hpp>
    #include <boost/mpl/bool.hpp>
    #include <boost/mpl/and.hpp>
    template <class T>
    struct is_rectangular
    {
        struct rectangular_check
        {
            template <class Value, class Dim>
            struct apply
            {
                typedef typename and_<
                    Value,
                    bool_<std::extent<T>::value == std::extent<T, Dim::value>::value>
                    >::type type;
            };
        };

        typedef typename fold<
            range_c<
                unsigned,
                0,
                std::rank<T>::value
                >,
            true_,
            rectangular_check
            >::type type;
    };

したがって、関数 (生の配列型を受け入れるように変更しました) は次のようになります。

    template <typename T, typename U>
    auto TensorSum(const T & t, const U &u )->
        decltype(std::declval<typename std::remove_all_extents<T>::type>() +
                 std::declval<typename std::remove_all_extents<U>::type>())
    {
        using SumType = decltype(std::declval<typename std::remove_all_extents<T>::type>() +
                                 std::declval<typename std::remove_all_extents<U>::type>());
        static_assert(std::rank<T>::value == std::rank<U>::value,
                      "The two tensors must have the same rank");

        // ToDo: Put a static assertion here to ensure tensors are rectangular
        std::cout << std::rank<T>::value << ' ' << std::extent<T>::value << std::endl;
        static_assert(is_rectangular<T>::type::value, "First tensor is not rectangular");
        static_assert(is_rectangular<U>::type::value, "Second tensor is not rectangular");

        SumType arrSum[std::rank<T>::value * std::extent<U>::value];
    }

    int main()
    {
        int a[10][10];
        TensorSum(a, a);
        return 0;
    }

ainの次元をmain必要に応じて異なるものに変更すると、これはコンパイルに失敗します。

これはもちろん、boost の助けを借りずに書くことができますが、できる限りそれを使用することを好みます。

于 2013-07-29T17:57:44.703 に答える