멀티 트 레딩을 사용하고 결과를 병합하려고합니다. 예를 들면 다음과 같습니다.
std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;
AB가 A의 내용과 B의 내용을 순서대로 갖기를 원합니다. 이와 같은 작업을 수행하는 가장 효율적인 방법은 무엇입니까?
멀티 트 레딩을 사용하고 결과를 병합하려고합니다. 예를 들면 다음과 같습니다.
std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;
AB가 A의 내용과 B의 내용을 순서대로 갖기를 원합니다. 이와 같은 작업을 수행하는 가장 효율적인 방법은 무엇입니까?
답변:
AB.reserve( A.size() + B.size() ); // preallocate memory
AB.insert( AB.end(), A.begin(), A.end() );
AB.insert( AB.end(), B.begin(), B.end() );
이것이 정확히 멤버 함수의 기능 std::vector::insert
입니다
std::vector<int> AB = A;
AB.insert(AB.end(), B.begin(), B.end());
insert
이 랜덤 액세스 반복기에 전문화 되어 있으며 사전에 예약되어 있다면 놀라지 않을 것 입니다.
distance
가 O (1) 복잡도를 가짐)라는 것도 알고 있기 때문에 이것은 좋은 지적 입니다. 여전히 성능 보장은 insert
미리 계획하여 더 잘 수행 할 수있는 경우를 염두에 두어야합니다.
size < capacity
대부분의 시간 이후 , 브랜치 예측은 비재 할당 브랜치의 명령이 명령 파이프 라인에있게하여 낮은 반복 횟수를 제외하고 브랜치 유발 레이턴시를 최소화합니다. 이것은 좋은 벡터 구현과 CPU 명령 파이프 라인 및 [좋은] 분기 예측을 가정하지만, 현대 툴체인과 데스크탑 머신에 대한 믿을만한 가정입니다. 그래도 스마트 폰에 대해 몰라 ..
실제로 두 벡터를 실제로 연결해야하는지 또는 반복을 위해 연결 모양을 제공 하려는지에 따라 다릅니다. 부스트 :: 결합 기능
http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html
당신에게 이것을 줄 것입니다.
std::vector<int> v0;
v0.push_back(1);
v0.push_back(2);
v0.push_back(3);
std::vector<int> v1;
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
...
BOOST_FOREACH(const int & i, boost::join(v0, v1)){
cout << i << endl;
}
너에게 줄거야
1
2
3
4
5
6
참고 boost :: join은 두 벡터를 새 컨테이너에 복사하지 않지만 두 컨테이너의 범위를 포함하는 한 쌍의 반복자 (범위)를 생성합니다. 약간의 성능 오버 헤드가 있지만 모든 데이터를 새 컨테이너에 먼저 복사하는 것보다 적을 수 있습니다.
Kiril V. Lyadvinsky의 답변을 바탕으로 새 버전을 만들었습니다. 이 스 니펫은 템플릿 및 과부하를 사용합니다. 그것으로, 당신은 쓸 수 vector3 = vector1 + vector2
및 vector4 += vector3
. 그것이 도움이되기를 바랍니다.
template <typename T>
std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B)
{
std::vector<T> AB;
AB.reserve(A.size() + B.size()); // preallocate memory
AB.insert(AB.end(), A.begin(), A.end()); // add A;
AB.insert(AB.end(), B.begin(), B.end()); // add B;
return AB;
}
template <typename T>
std::vector<T> &operator+=(std::vector<T> &A, const std::vector<T> &B)
{
A.reserve(A.size() + B.size()); // preallocate memory without erase original data
A.insert(A.end(), B.begin(), B.end()); // add B;
return A; // here A could be named AB
}
::
촬영)
v1 + v2
추가 를 나타내지 않는 것은 분명 하지 않습니다.
@
F 번호처럼
Bradgonesurfing의 대답의 방향으로, 많은 경우 실제로 두 벡터 (O (n))를 연결할 필요 가 없지만 대신 연결된 것처럼 (O (1)) 작동 합니다. 이 경우 Boost 라이브러리가 없어도 가능합니다.
트릭은 벡터 프록시를 만드는 것입니다 : 참조 를 조작하는 래퍼 클래스 는 두 개의 벡터에 를 외부에서 하나의 연속 된 것으로 간주하여 합니다.
용법
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1). No copies performed.
for (size_t i = 0; i < AB.size(); ++i)
std::cout << AB[i] << " "; // 1 2 3 4 5 10 20 30
이행
template <class T>
class VecProxy {
private:
std::vector<T>& v1, v2;
public:
VecProxy(std::vector<T>& ref1, std::vector<T>& ref2) : v1(ref1), v2(ref2) {}
const T& operator[](const size_t& i) const;
const size_t size() const;
};
template <class T>
const T& VecProxy<T>::operator[](const size_t& i) const{
return (i < v1.size()) ? v1[i] : v2[i - v1.size()];
};
template <class T>
const size_t VecProxy<T>::size() const { return v1.size() + v2.size(); };
주요 혜택
그것을 만드는 데는 O (1) (일정 시간)이며 최소한의 추가 메모리 할당이 있습니다.
고려해야 할 몇 가지
아직 언급되지 않은 또 하나의 간단한 변형 :
copy(A.begin(),A.end(),std::back_inserter(AB));
copy(B.begin(),B.end(),std::back_inserter(AB));
그리고 병합 알고리즘을 사용하십시오.
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
#include <sstream>
#include <string>
template<template<typename, typename...> class Container, class T>
std::string toString(const Container<T>& v)
{
std::stringstream ss;
std::copy(v.begin(), v.end(), std::ostream_iterator<T>(ss, ""));
return ss.str();
};
int main()
{
std::vector<int> A(10);
std::vector<int> B(5); //zero filled
std::vector<int> AB(15);
std::for_each(A.begin(), A.end(),
[](int& f)->void
{
f = rand() % 100;
});
std::cout << "before merge: " << toString(A) << "\n";
std::cout << "before merge: " << toString(B) << "\n";
merge(B.begin(),B.end(), begin(A), end(A), AB.begin(), [](int&,int&)->bool {});
std::cout << "after merge: " << toString(AB) << "\n";
return 1;
}