2011-10-31 31 views
1

這是我第一次嘗試使用QtConcurrent :: blockingMappedReduced,並且我無法在MSVC 2010 Express(使用QT 4.7.1源代碼)中構建它。QtConcurrent blockingMappedReduced error

我創建了一個小例子,類似於我的實際代碼,並有同樣的問題建築:

// 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++技能不是專家,所以幫助需要明確以便我理解它(例如,實際的代碼片段,而不是那些比我有更多知識的東西,比如「你的論點必須是一個常量引用」 )。

在此先感謝您的幫助。

回答

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作爲個人偏好設置。)

What should main() return in C and C++?

至於你QtConcurrent問題,有幾個。首先你的QList是整數,文檔指出序列中的類型應該和map函數的第一個參數相匹配(如果你有雙精度的話)。所以QList需要改變爲雙 - 或 - 你的地圖功能需要一個整數。

你有另外一個問題是,你正在試圖指向成員函數傳遞到意想不到只是純醇功能插槽的事實:

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

注意,不存在myClassInstance提到除了聲明。在一般情況下...解決這個問題並不像改變呼叫使用&myClassInstance::mapFunction, &myClassInstance::reduceFunction那麼簡單。當你位於C環顧四周++,你會發現沒有製造出能適合任何插槽一個函數調用的對象通常可行的方法,即使它們被設計用來似乎是調用類的函數:

Help with boost bind/functions

幸運的是,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」或「普通舊數據」類型並且沒有方法調度)。那麼該參數是隱含的。

但請注意,如果你想使用這種技術,它會以特定的方式風格化代碼。這裏是變化:

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作爲成員。但是要改變輸入序列類型很醜陋,而且這不是過程參數的正確位置 - 你需要一個函數對象。

(的同時也要記住,一個可寫狀態,地圖功能可以得到破壞的MapReduce並行性。該地圖操作都應該讓他們保持獨立,真正只能通過他們的結果產生輸出...)

+0

HostileFork:感謝您的解決方案。除了一般的C++清理以外,下面是與blockingMappedReduced相關的問題:1)map和reduce函數不能成爲成員函數,但必須是全局函數,2)我的中間類從地圖傳遞值函數的reduce函數需要一個默認的構造函數,3)map函數的類型不是const。後續問題:QT文檔給出了一個使用map和reduce爲QtConcurrent :: mappedReduced使用成員函數的示例。但是這不適用於blockingMappedReduced? – user1020872

+0

要回答我自己的後續問題,使用成員函數時,顯然它們必須是靜態的。 – user1020872

+0

我可以問你一些關於你的C++清理我的代碼的問題嗎? 1)爲什麼中間對象使用結構而不是類是可取的? 2)爲什麼最好沒有中間對象的嵌套類?我的動機是,我的實際代碼中的myClass是封裝了許多其他事物的類,而不僅僅是我在示例中展示的簡單事物。 – user1020872

2

HostileFork:再次感謝您的幫助。你讓我重返正軌,讓我真正的代碼工作。

爲了完整起見,下面是我的原始示例,其中需要進行最小的更改,以便進行blockingMappedReduced工作(但仍然伴隨着我亂七八糟的C++樣式問題)。這就是我通過解決方案來理解什麼是什麼的。它可能幫助其他人排序通過哪些阻塞映射減少的問題,哪些是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); 
} 
+0

啊,起初我並沒有意識到你想要最大的結果輸入(沒有找到最大的輸入和輸出)。雖然你可以重命名變量來嘗試做出更明顯的事情,但請注意,如果你已經聲明瞭MapResult類型,那麼你可以重新使用這種類型......我改變了我的代碼來做到這一點。還要注意對構造函數的更改('Temp :: Temp' =>'Temp')和main的返回類型不是多餘的。無論MSVC 2010是否願意爲您編譯,它都是不正確的C++,並且不會在符合標準的編譯器上編譯。 – HostileFork

+0

再次感謝您的建議。在我的實際代碼中,我沒有在一個文件中包含所有內容,構造函數原型位於頭文件中,實現位於cpp文件中,並且原型按照您的建議。而我的實際主要功能確實返回一個int狀態。但我的例子可能會讓其他人閱讀它,所以我會編輯它。 – user1020872