我有兩個數組。一個是「x」因素與第二個的大小。有效的方法複製數組與面具在c + +
我需要從第一(較大的)陣列到第二(較小)陣列僅其x元件複製。 含義0,x,2x。
每個數組都位於內存中的一個塊中。 該數組具有簡單的值。 我目前正在使用循環。
有沒有更快更聰明的方法來做到這一點?
與ostream
也許? 謝謝!
我有兩個數組。一個是「x」因素與第二個的大小。有效的方法複製數組與面具在c + +
我需要從第一(較大的)陣列到第二(較小)陣列僅其x元件複製。 含義0,x,2x。
每個數組都位於內存中的一個塊中。 該數組具有簡單的值。 我目前正在使用循環。
有沒有更快更聰明的方法來做到這一點?
與ostream
也許? 謝謝!
你正在做這樣的事情嗎?
#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;
}
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選項)。
這是否真的符合「更智能和更快」的要求?似乎不太可能。 –
@BenjaminLindley nope,但它很酷 – aaronman
,如果我得到你的權利,你想每隔第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;
}
就像一個側面注意分支('如果(pout>&out [4])')可能是昂貴的,如果它是一個熱循環,但這實際上是一個循環不變的,所以它可移動到然後調整環路條件。 – Alex
這樣做的正確的清潔方式是像以前所說的循環。這裏有很多好的答案告訴你如何做到這一點。
我不建議按照以下方式去做,它取決於很多具體的事情,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,此方法不起作用,或者對於未分配的值線性時尚。它也不適用於類。
對於這種優化是值得的麻煩代碼需要運行往往,我假設你已經運行一個分析器,以確認在執行這樣的事情之前,舊的副本是一個瓶頸。
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());
}
以下是關於大多數CPU設計如何在這類事情上毫無想象力的觀察。
在某些的OpenVPX你有能力DMA數據從一個處理器到另一個。我使用的是一個非常先進的DMA控制器,它可以爲你做這種事情。
例如,我可以要求它將您的大陣列複製到另一個CPU,但跳過陣列中的N個元素,就像您正在嘗試的那樣。就像通過魔術一樣,目標CPU的內存中會有更小的陣列。我也可以,如果我想執行矩陣轉換等。
好的是,它不需要CPU時間就可以做到這一點;它全部由DMA引擎完成。然後,我的CPU可以集中精力投入更多的資金,而不是將數據捆綁在一起。我認爲PS3中的Cell處理器可以在內部做這種事情(我知道它可以DMA數據,我不知道它是否會同時進行條帶挖掘)。一些DSP芯片也可以做到這一點。但x86不這樣做,這意味着我們的軟件程序員必須編寫荒謬的循環,只是以簡單模式移動數據。打哈欠。
我寫過一個多線程的memcpy()來做這種事情。要打敗for循環的唯一方法是讓幾個線程在幾個並行塊中進行循環。
如果你選擇了正確的編譯器(例如Intel的ICC或Sun/Oracles Sun Studio),他們可以自動代表你的for循環(所以你的源代碼不會改變)。這可能是最簡單的方法來打敗你原來的循環。
將您當前的代碼添加到問題中。 –
在您處理問題時將您的表現要求添加到問題中。這聽起來不像一個理智的應用程序將受到限制... –
告訴我們你的代碼! – minicaptain