2017-03-07 105 views
1

項的大小,我需要補矩陣(std::vector< std::vector<T> >)是已知的,已經使用vector::resize(...)功能設置的行和列,其數量。在omp循環中填充已知大小的矩陣。未知

每個矩陣元素的對象都是class T的對象,它們應該具有std::set<int>作爲其中的成員。沒有辦法事先知道這些設置的大小。

爲了填補我的目標是使用一個循環像以下,其中m的矩陣,N是公知的數字:

std::vector<T> innerVector; 
innerVector.resize(n, T()); 

std::vector< std::vector<T> > myMatrix; 
myMatrix.resize(m, innerVector); 

#pragma omp parallel for 
for(size_t i = 0; i < myMatrix.size(); ++i) 
{ 
    for(size_t j = 0; j < myMatrix.at(0).size(); ++j) 
    { 
     fillMatrix(myMatrix, i, j); 
    } 
} 

fillMatrix(...)函數並只使用已知的信息來建立該組中包含的號碼的每個矩陣元素,所以在那裏沒有數據依賴。

灌裝這樣我們就不會遇到造成多個線程同時訪問一個矩陣元素比賽條件的矩陣。我的問題是,在不使用omp critical環境的情況下調用fillMatrix(...)函數是否安全。

關鍵是我不知道vector::resize(...)功能是如何工作的。不知何故,它爲myMatrix分配了一些內存,但由於class T的元素大小未知,我可以想象遇到這種情況,原來分配給矩陣元素的內存是不夠的。然後會發生什麼?是否有可能多個線程(即填充不同矩陣條目的線程)嘗試使用相同的地址擴展分配的內存?

回答

1

許多複雜的對象,如std::vectorstd::set由對象本身的內存(即sizeof(std::vector)字節)和其後的動態分配內存組成。對於你的例子,集合元素通常存儲在樹的動態分配節點中。因此,如果您執行std::vector<T>::resize(n),向量將確保它自己的動態分配的內存可以包含n類型爲T的對象,每個對象都包含一個集合。它會default-construct使用這些元素當您稍後將元素添加到T內部的集合中時,將爲該集合的樹節點分配新的內存塊。

你描述它的樣子,你應該在正確的方面是好的。不過,我會強烈建議您在界面中澄清這一點:

void fillMatrix(T&, size_t, size_t); 
... 
fillMatrix(myMatrix[i][j], i, j); 

甚至:

T fillMatrix(size_t, size_t); 
... 
myMatrix[i][j] = fillMatrix(i, j); 

這種方式,它更清晰的是fillMatrix不從其他線程亂七八糟的數據。

共享存儲器編程通常建議分配和線程很可能與內存以後的工作中,初始化的內存。所以,如果你會做更多的myMatrixparallel for,考慮以下因素:

std::vector< std::vector<T> > myMatrix; 
myMatrix.resize(m); 

#pragma omp parallel for 
for(size_t i = 0; i < myMatrix.size(); ++i) 
{ 
    myMatrix.at(i).resize(n); // Ommiting T() is a bit more efficient 
    for(size_t j = 0; j < n; ++j) 
    { 
     fillMatrix(myMatrix, i, j); 
    } 
} 

然而,在任何情況下,代碼可能會被分配內存的限制(無論是添加元素std::setstd::vector::resize)。因此,除非fillMatrix執行了重要的附加計算,否則不應該期望代碼的該特定部分的並行性能提高。但是,這些數據可能位於緩存/ NUMA節點上,靠近元素上的線程計算,所以其餘並行代碼可以高效地進行計算。