2013-07-31 17 views
0

我有兩個數組。一個是「x」因素與第二個的大小。有效的方法複製數組與面具在c + +

我需要從第一(較大的)陣列到第二(較小)陣列僅其x元件複製。 含義0,x,2x。

每個數組都位於內存中的一個塊中。 該數組具有簡單的值。 我目前正在使用循環。

有沒有更快更聰明的方法來做到這一點?

ostream

也許? 謝謝!

+2

將您當前的代碼添加到問題中。 –

+0

在您處理問題時將您的表現要求添加到問題中。這聽起來不像一個理智的應用程序將受到限制... –

+1

告訴我們你的代碼! – minicaptain

回答

2

你正在做這樣的事情嗎?

#include <cstddef> 

int main() 
{ 
    const std::size_t N = 20; 
    const std::size_t x = 5; 
    int input[N*x]; 
    int output[N]; 

    for(std::size_t i = 0; i < N; ++i) 
    output[i] = input[i*x]; 
} 

好了,我不知道能做到這一點的任何功能,所以我會用for循環。這很快。

編輯:甚至更快溶液(以避免乘法)(C++ 03版)

int* inputit = input; 
int* outputit = output; 
int* outputend = output+N; 

while(outputit != outputend) 
{ 
    *outputit = *inputit; 
    ++outputit; 
    inputit+=x; 
} 
+2

您可以嘗試避免指數計算中的乘法。而是爲我添加一個固定的偏移量。應該使它快一點 – Alex

+1

我不想說出你的話,因爲處理器成本是相似的,並且它也不會幫助,因爲[]運算符總是使用乘法運算,無論如何,如果你想優化到最大值,那麼使用指針算術。 – dieram3

+0

如果乘法是2的乘方,則算術優化器會將其減小到無論如何。如果一個合適的優化器不會執行乘法來執行'[]',我不會感到驚訝。在任何情況下,運作都應該基於他的選擇。因爲我們不知道他的編譯器會對代碼做些什麼。 – Alex

1

可以在C++ 11使用copy_iflambda

copy_if(a.begin(), a.end(), b.end(), [&] (const int& i) -> bool 
{ size_t index = &i - &a[0]; return index % x == 0; }); 

測試用例將是:

#include <iostream> 
#include <vector> 
#include <algorithm> // std::copy_if 

using namespace std; 


int main() 
{ 
    std::vector<int> a; 
    a.push_back(0); 
    a.push_back(1); 
    a.push_back(2); 
    a.push_back(3); 
    a.push_back(4); 

    std::vector<int> b(3); 

    int x = 2; 

    std::copy_if(a.begin(), a.end(), b.begin(), [&] (const int& i) -> bool 
{ size_t index = &i - &a[0]; return index % x == 0; }); 

    for(int i=0; i<b.size(); i++) 
    { 
     std::cout<<" "<<b[i]; 
    } 

    return 0; 
} 

請注意,您需要使用C++ 11兼容的編譯器(GCC是否機智h -std = C++ 11選項)。

+3

這是否真的符合「更智能和更快」的要求?似乎不太可能。 –

+1

@BenjaminLindley nope,但它很酷 – aaronman

1

,如果我得到你的權利,你想每隔第n個元素複製。最簡單的解決辦法是

#include <iostream> 
int main(int argc, char **argv) { 
    const int size[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
    int out[5]; 
    int *pout = out; 
    for (const int *i = &size[0]; i < &size[10]; i += 3) { 
     std::cout << *i << ", "; 
     *pout++ = *i; 
     if (pout > &out[4]) { 
      break; 
     } 
    } 
    std::cout << "\n"; 
    for (const int *i = out; i < pout; i++) { 
     std::cout << *i << ", "; 
    } 
    std::cout << std::endl; 
} 
+0

就像一個側面注意分支('如果(pout>&out [4])')可能是昂貴的,如果它是一個熱循環,但這實際上是一個循環不變的,所以它可移動到然後調整環路條件。 – Alex

0

這樣做的正確的清潔方式是像以前所說的循環。這裏有很多好的答案告訴你如何做到這一點。

我不建議按照以下方式去做,它取決於很多具體的事情,X的取值範圍,變量的大小和取值範圍等等,但對於一些你可以這樣做:

for every 4 bytes: 
    tmp = copy a 32 bit variable from the array, this now contains the 4 new values 
    real_tmp = bitmask tmp to get the right variable of those 4 
    add it to the list 

這隻適用於如果你想要的值< = 255和X == 4,但如果你想要的東西比循環更快,這是一種做法。這可以修改爲16位,32位或64位值和每個2,3,4,5,6,7,8(64位)值,但對於X> 8,此方法不起作用,或者對於未分配的值線性時尚。它也不適用於類。

對於這種優化是值得的麻煩代碼需要運行往往,我假設你已經運行一個分析器,以確認在執行這樣的事情之前,舊的副本是一個瓶頸。

1
template<typename InIt, typename OutIt> 
void copy_step_x(InIt first, InIt last, OutIt result, int x) 
{    
    for(auto it = first; it != last; std::advance(it, x)) 
     *result++ = *it; 
} 

int main() 
{ 
    std::array<int, 64> ar0; 
    std::array<int, 32> ar1; 
    copy_step_x(std::begin(ar0), std::end(ar0), std::begin(ar1), ar0.size()/ar1.size()); 
} 
0

以下是關於大多數CPU設計如何在這類事情上毫無想象力的觀察。

在某些的OpenVPX你有能力DMA數據從一個處理器到另一個。我使用的是一個非常先進的DMA控制器,它可以爲你做這種事情。

例如,我可以要求它將您的大陣列複製到另一個CPU,但跳過陣列中的N個元素,就像您正在嘗試的那樣。就像通過魔術一樣,目標CPU的內存中會有更小的陣列。我也可以,如果我想執行矩陣轉換等。

好的是,它不需要CPU時間就可以做到這一點;它全部由DMA引擎完成。然後,我的CPU可以集中精力投入更多的資金,而不是將數據捆綁在一起。我認爲PS3中的Cell處理器可以在內部做這種事情(我知道它可以DMA數據,我不知道它是否會同時進行條帶挖掘)。一些DSP芯片也可以做到這一點。但x86不這樣做,這意味着我們的軟件程序員必須編寫荒謬的循環,只是以簡單模式移動數據。打哈欠。

我寫過一個多線程的memcpy()來做這種事情。要打敗for循環的唯一方法是讓幾個線程在幾個並行塊中進行循環。

如果你選擇了正確的編譯器(例如Intel的ICC或Sun/Oracles Sun Studio),他們可以自動代表你的for循環(所以你的源代碼不會改變)。這可能是最簡單的方法來打敗你原來的循環。

相關問題