1

これは、QtConcurrent ::blockingMappedReducedを使用する最初の試みであり、MSVC 2010 Express(QT 4.7.1ソースコードを使用)でビルドすることはできません。

実際のコードに似た小さな例を作成しましたが、同じ問題が発生します。

// Here's the general outline:
// 1. create a list of random numbers
// 2. pass the list to blockingMappedReduced
// 3. the map function calculates the sine of the given random number
// 4. the reduce function finds the random number with the maximum sine value

// Here's the implementation:

#include "stdafx.h"
#include <qlist.h>
#include <qtconcurrentmap.h>

// My class for the map/reduce functions
class myClass
{
private:

    // Nested class to hold the intermediate results from the map function
    // I think I need this because the reduce function needs more from the map function than a single return value
    class Temp
    {
    public:

        // For example, let's pass these two member variables from the map function to the reduce function
        int randomInput;
        double resultingOutput;

        // The Temp constructor
        Temp::Temp(double randomInput, double resultingOutput)
        {
            this->randomInput = randomInput;
            this->resultingOutput = resultingOutput;
        }
    };

public:

    // For example, these myClass members will hold the final result from the reduce function
    double maximumOutput;
    double maximumInput;

    // The myClass constructor
    myClass::myClass()
    {
        this->maximumOutput = -1;
    }

    // The map function
    const Temp mapFunction(const double& randomInput)
    {
        // For example, let's calculate the sine of the given random number
        double resultingOutput = sin(randomInput);

        // Construct the temporary structure to pass multiple values to the reduce function
        const Temp temp(randomInput, resultingOutput);
        return(temp);
    }

    // The reduce function
    void reduceFunction(double& maxInput, const Temp& temp)
    {
        // For example, let's find the maximum computed sine value
        if (temp.resultingOutput > this->maximumOutput)
        {
            this->maximumOutput = temp.resultingOutput;
            this->maximumInput = temp.randomInput;
        }

        maxInput = this->maximumInput;
    }
};

// Main function
void main(int argc, _TCHAR* argv[])
{
    // Build a list of random numbers
    QList<int> aList;
    for (int count = 8; count > 0; --count)
    {
        aList.append(rand());
    }

    // Invoke the parallel map/reduce function
    myClass myClassInstance;
    double theAnswer = QtConcurrent::blockingMappedReduced(aList, &myClass::mapFunction, &myClass::reduceFunction);
}

コンパイラは、blockingMappedReducedが呼び出される最後の行について文句を言います。

c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'D QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__thiscall C::* )(void) const,U (__thiscall D::* )(V),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(659) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'C QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__cdecl *)(U),V (__thiscall C::* )(W),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(643) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'V QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__thiscall C::* )(void) const,U (__cdecl *)(V &,W),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(627) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'W QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__cdecl *)(U),V (__cdecl *)(W &,X),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(611) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__thiscall C::* )(void) const,ReduceFunctor,QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(595) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__cdecl *)(U),ReduceFunctor,QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(579) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'C QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,T (__thiscall C::* )(U),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(563) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'U QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,T (__cdecl *)(U &,V),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(547) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(536) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'D QtConcurrent::blockingMappedReduced(const Sequence &,T (__thiscall C::* )(void) const,U (__thiscall D::* )(V),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::* )(void) const' from 'const myClass::Temp (__thiscall myClass::* )(const double &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(522) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'C QtConcurrent::blockingMappedReduced(const Sequence &,T (__cdecl *)(U),V (__thiscall C::* )(W),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U)' from 'const myClass::Temp (__thiscall myClass::* )(const double &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(508) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'V QtConcurrent::blockingMappedReduced(const Sequence &,T (__thiscall C::* )(void) const,U (__cdecl *)(V &,W),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::* )(void) const' from 'const myClass::Temp (__thiscall myClass::* )(const double &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(494) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'W QtConcurrent::blockingMappedReduced(const Sequence &,T (__cdecl *)(U),V (__cdecl *)(W &,X),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U)' from 'const myClass::Temp (__thiscall myClass::* )(const double &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(480) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,T (__thiscall C::* )(void) const,ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::* )(void) const' from 'const myClass::Temp (__thiscall myClass::* )(const double &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(466) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,T (__cdecl *)(U),ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U)' from 'const myClass::Temp (__thiscall myClass::* )(const double &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(452) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'C QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,T (__thiscall C::* )(U),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::* )(U)' from 'void (__thiscall myClass::* )(double &,const myClass::Temp &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(438) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'U QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,T (__cdecl *)(U &,V),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U &,V)' from 'void (__thiscall myClass::* )(double &,const myClass::Temp &)'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(424) : see declaration of 'QtConcurrent::blockingMappedReduced'
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2783: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'ResultType'
          c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(414) : see declaration of 'QtConcurrent::blockingMappedReduced'

オンラインQTドキュメント(http://doc.qt.nokia.com/4.7-snapshot/qtconcurrentmap.html#blockingMappedReduced)から、プロトタイプは次のとおりです。

T  blockingMappedReduced ( const Sequence & sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce ) 

私にはこれをデバッグするための専門知識がないのではないかと思います。どんな助けでも大歓迎です。繰り返しになりますが、私のC ++スキルは専門家ではないため、理解するにはヘルプを明示する必要があります(つまり、「引数は常に参照する必要があります」のように、私が持っている以上の知識を前提とするものではなく、実際のコードスニペットです。 )。

よろしくお願いします。

4

2 に答える 2

2

あなたのコードには、QtConcurrent に関連しない、パッチを適用する必要のある一般的な問題がいくつかあります。まず、コンストラクターを修飾しないでください。代わりに、次のようにします。

    // The Temp constructor
    Temp::Temp(double randomInput, double resultingOutput)

簡単に書く必要があります:

    // The Temp constructor
    Temp(double randomInput, double resultingOutput)

についても同じですmyClass。また、main の関数シグネチャは常に を返す必要がありintますが、C99 および C++ では、0 を返したい場合は return ステートメントを省略できます (ただし、return 0個人的な好みの問題として、常に明示的に記述します)。

main() は C および C++ で何を返す必要がありますか?

QtConcurrent の問題に関しては、いくつかあります。最初に QList は整数であり、ドキュメントでは、シーケンスの型が map 関数の最初のパラメーター (double がある場合) と一致する必要があることを指摘しています。したがって、QList を double に変更する必要があります。または、map 関数が int を受け取る必要があります。

あなたが抱えているもう1つの問題は、メンバー関数へのポインタを単純な関数だけを期待するスロットに渡そうとしていることです:

    // Invoke the parallel map/reduce function
    myClass myClassInstance;
    double theAnswer = QtConcurrent::blockingMappedReduced(aList,
        &myClass::mapFunction, &myClass::reduceFunction);

myClassInstance宣言以外の言及がないことに注意してください。一般的なケースでは...これを回避することは、呼び出しを use に変更するほど簡単ではありません&myClassInstance::mapFunction, &myClassInstance::reduceFunction。C++ を見回すと、関数のように呼び出し可能に見えるように設計されていても、関数呼び出しが可能な任意のスロットに収まるオブジェクトを作成する一般的に実行可能な方法がないことがわかります。

ブーストバインド/機能のヘルプ

幸いなことに、QtConcurrent はこれで窮地に陥ることはありません。関数オブジェクトの必要性を予測しました。

http://doc.qt.io/archives/qt-4.7/qtconcurrentmap.html#using-function-objects

ただし、それを機能させる方法を掘り下げるのではなく、そもそもなぜこれらをメンバー関数として使用する必要があるのか​​を検討する必要があります。Map/Reduce モデルを使用すると、カスタムのアキュムレータと結果の型を定義できるため、問題なく必要なものを取得できます。これは、うまくいけばコンパイルしてあなたを近づけるより単純なバージョンです:

#include <qlist.h>
#include <qtconcurrentmap.h>

#include <cmath> // for sin()
#include <algorithm> // for min, max, etc.
#include <limits> // for numeric_limits

struct MapResult // same as class, but "public" by default
{
    double input;
    double output;

    // must be "default constructible" due to guts of QtConcurrent :-/    
    // implementation artifact, don't worry about it affecting you...
    MapResult () {}

    MapResult (double input, double output) :
        // initializing members like this is cleaner than this->x = x...
        // and for certain members you HAVE to do it this way
        input (input), output (output)
    {
    }
};

struct ReduceAccumulator // same as class, but "public" by default
{
    MapResult largest;

    ReduceAccumulator () :
        // a better choice than 0 for an "uninitialized max" since
        // any other double will be larger...but you really should
        // probably accomodate a "no entries" case
        largest (MapResult (0, std::numeric_limits<double>::min())
    {
    }
};

// pattern of return type should be "U", not "const U" according to docs
MapResult mapFunction(const double& input) 
{
    // no need to construct a named local var if you don't want to
    // also no parentheses needed on return(x); ... return x; is fine 
    return MapResult (input, sin(input));
}

void reduceFunction(ReduceAccumulator& acc, const MapResult& oneResult)
{
    if (oneResult.output > acc.largest.output) {
        acc.largest = oneResult
    }
}

int main(int argc, char* argv[])
{
    QList<double> aList;
    for (int count = 8; count > 0; --count)
    {
        aList.append(rand());
    }

    ReduceAccumulator answer = QtConcurrent::blockingMappedReduced(
        aList, &mapFunction, &reduceFunction);

    return 0;
}

いくつかの一般的な C++ ノートが含まれています。うまくいけば役に立ちます...


UPDATE : 彼らが提供する別のルートはメンバー関数を使用しますが、記述しようとしていたスタイルとはいくつかの異なる仮定をしています。まず、シーケンス入力タイプがクラス ( double「POD」または「plain-old-data」タイプであり、メソッド ディスパッチを持たない) であると想定しています。その場合、パラメーターは暗黙的です。

ただし、この手法を使用する場合は、コードが特定の方法でスタイル化されることに注意してください。変更点は次のとおりです。

struct ReduceAccumulator
{
    MapResult largest;

    ReduceAccumulator () :
        largest (MapResult(0, std::numeric_limits<double>::min())
    {
    }

    // runs on non-const object, and drops first parameter (now implicit)
    void reduceFunction(const MapResult& oneResult)
    {
        if (oneResult.output > largest.output) {
            largest = oneResult
        }
    }
};

struct MyDouble {
    double d;

    MyDouble (double d) : d (d) {}

    // as member it takes no arguments, and needs to run on const objects
    MapResult mapFunction() const 
    {
        return MapResult (d, sin(d));
    }
};

int main(int argc, char* argv[])
{
    // to use a member as mapFunction, must be a member of input sequence type
    QList<MyDouble> aList;
    for (int count = 8; count > 0; --count)
    {
        aList.append(MyDouble (rand()));
    }

    ReduceAccumulator theAnswer = QtConcurrent::blockingMappedReduced(
        aList, &MyDouble::mapFunction, &ReduceAccumulator::reduceFunction);
}

選択して選択できます...この場合、メンバーとして reduceFunction を実行する方がおそらく良いでしょう。しかし、入力シーケンスの型を変更するのはちょっと厄介です。それは、プロセスへのパラメーターの適切な場所ではありません。関数オブジェクトが必要です。

(また、map 関数が書き込み可能な状態になると、MapReduce の並列性が損なわれることにも注意してください。map 操作は、実際には結果を介してのみ出力を生成することになっているため、独立したままになります...)

于 2011-11-01T01:29:44.500 に答える
2

HostileFork: ご協力ありがとうございます。あなたのおかげで、私の実際のコードを機能させることができるようになりました。

完全を期すために、blockingMappedReduced を機能させるために必要な最小限の変更を加えた元の例を次に示します (ただし、私の厄介な C++ スタイルの問題はまだ残っています)。これが、何が何であるかを理解するためにあなたのソリューションをどのように処理したかです。他の誰かが、blockingMappedReduced の問題と C++ の問題を分類するのに役立つかもしれません。

#include "stdafx.h"
#include <qlist.h>
#include <qtconcurrentmap.h>


// My class for the map/reduce functions
class myClass
{
    // Nested class to hold the intermediate results from the map function
    // I think I need this because the reduce function needs more from the map function than a single return value
    class Temp
    {
    public:

        // For example, let's pass these two member variables from the map function to the reduce function
        int randomInput;
        double resultingOutput;

        // default Temp constructor
        Temp()
        {
        };

        // The Temp constructor
        Temp(double randomInput, double resultingOutput)
        {
            this->randomInput = randomInput;
            this->resultingOutput = resultingOutput;
        }
    };

public:

    // For example, these myClass members will hold the final result from the reduce function
    double maximumOutput;
    double maximumInput;

    // The myClass constructor
    myClass()
    {
        this->maximumOutput = -1;
    }

    // The map function
    static Temp myClass::mapFunction(const int& randomInput)
    {
        // For example, let's calculate the sine of the given random number
        double resultingOutput = sin((double)randomInput);

        // Construct the temporary structure to pass multiple values to the reduce function
        Temp temp(randomInput, resultingOutput);
        return(temp);
    }

    // The reduce function
    static void myClass::reduceFunction(myClass& accumulator, const Temp& temp)
    {
        // For example, let's find the maximum computed sine value
        if (temp.resultingOutput > accumulator.maximumOutput)
        {
            accumulator.maximumOutput = temp.resultingOutput;
            accumulator.maximumInput = temp.randomInput;
        }
    }
};


// Main function
int main(int argc, _TCHAR* argv[])
{
    // Build a list of random numbers
    QList<int> aList;
    for (int count = 8; count > 0; --count)
    {
        aList.append(rand());
    }

    // Invoke the parallel map/reduce function
    myClass theAnswer = QtConcurrent::blockingMappedReduced(aList, &myClass::mapFunction, &myClass::reduceFunction);

    return(0);
}
于 2011-11-01T08:07:15.133 に答える