I need to start execution of vector of tasks in parallel and wait until finished. Here is how I did this, but I get future_error on MSVC. Small utility to split vector into parts:
template<typename T>
vector<vector<T>> split(const vector<T>& vec, size_t n) {
vector<vector<T>> outVec;
size_t length = vec.size() / n;
size_t remain = vec.size() % n;
size_t begin = 0;
size_t end = 0;
for (size_t i = 0; i < std::min(n, vec.size()); ++i) {
end += (remain > 0) ? (length + !!(remain--)) : length;
outVec.push_back(std::vector<T>(vec.begin() + begin, vec.begin() + end));
begin = end;
}
return outVec;
};
launch async execution:
template <typename T, typename R, typename F>
void execInParallel(vector<T> &tasks, vector<R> &res, F&&f, int cores) {
function<int(int &t)> fn(std::forward<F>(f));
auto parts = split(tasks, cores);
vector<future<vector<R>>*> threads;
for (auto part: parts) {
future<vector<R>> thrd=async(launch::async, [&](vector<T> tasks) {
vector<R> rs;
for (auto&t : tasks) {
rs.push_back(fn(t));
}
return rs;
}, part);
threads.push_back(&thrd);
}
for (auto&thrd : threads) {
vector<R> rs = thrd->get();
for (auto &r : rs)
res.push_back(r);
}
};
test on stupid example:
int main(){
vector<int> tasks,res;
tasks.push_back(1);
tasks.push_back(7);
tasks.push_back(19);
execInParallel(tasks,res, [&](int&t) {
return t+8;
}, 2);
return 0;
}
May be I am inventing a bicycle? Is there anything like that in C++11 or boost out of the box? Any example available?
Related
I need to overload the + operation like this a + b = max(a,b).
And accordingly I need it to work for matrix addition and matrix multiplication and some other operations (trace, power,etc.). Here \bigoplus is max operation
What's the best way to do this with Eigen? I read about eigen extension here, but I don't understand how to do that for my task.
Currently I have this:
#include <iostream>
#include <Eigen/Dense>
#include <algorithm>
using namespace Eigen;
namespace MaxAlgebra {
template <typename T>
T operator+(const T& a,const T& b) {
T c(a.rows(),a.cols());
for (uint i = 0; i < a.rows(); ++i) {
for (uint j = 0; j < a.cols(); ++j) {
c(i,j) = std::max(a(i,j),b(i,j));
}
}
return c;
}
template <typename T>
T operator*(const T& a,const T& b){
T c(a.rows(),b.cols());
for (uint i = 0; i < a.rows(); ++i) {
for (uint j = 0; j < b.cols(); ++j) {
std::vector<uint> values;
for (uint k = 0; k < a.cols(); ++k) {
values.push_back(a(i,k) * b(k,j));
}
c(i,j) = *std::max_element(begin(values),end(values));
}
}
return c;
}
template <typename T>
uint trace(const T& a) {
std::vector<uint> values;
for (uint i = 0; i < a.rows(); ++i) {
values.push_back(a(i,i));
}
return *std::max_element(begin(values),end(values));
}
}
int main() {
MatrixXd x(2,2);
MatrixXd y(2,2);
x(0,0) = 3;
x(1,0) = 2;
x(0,1) = 1;
x(1,1) = 2;
y(0,0) = 2;
y(1,0) = 1;
y(0,1) = 2;
y(1,1) = 3;
MatrixXd c = MaxAlgebra::operator*(x,y);
std::cout << "Here is the matrix a:\n" << x << std::endl;
std::cout << "Here is the matrix b:\n" << y << std::endl;
std::cout << "Here is the matrix c:\n" << c << std::endl;
return 0;
}
If I understand your algebra correctly, you could simply create a custom scalar type. This seems to work:
template<class T>
struct MaxAlg
{
T scalar;
MaxAlg() = default;
MaxAlg(T scalar) noexcept // implicit conversion for convenience
: scalar(scalar)
{}
explicit operator T() const noexcept
{ return scalar; }
MaxAlg& operator+=(MaxAlg o) noexcept
{
scalar = std::max(scalar, o.scalar);
return *this;
}
friend MaxAlg operator+(MaxAlg left, MaxAlg right) noexcept
{ left += right; return left; }
MaxAlg& operator*=(MaxAlg o) noexcept
{
scalar *= o.scalar;
return *this;
}
friend MaxAlg operator*(MaxAlg left, MaxAlg right) noexcept
{ left *= right; return left; }
friend bool operator==(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar == right.scalar; }
friend bool operator!=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar != right.scalar; }
friend bool operator<(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar < right.scalar; }
friend bool operator<=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar <= right.scalar; }
friend bool operator>(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar > right.scalar; }
friend bool operator>=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar >= right.scalar; }
friend std::ostream& operator<<(std::ostream& left, MaxAlg right)
{ return left << right.scalar; }
};
template<class T, Eigen::Index Rows, Eigen::Index Cols>
using MaxAlgMatrix = Eigen::Matrix<MaxAlg<T>, Rows, Cols>;
template<class T, Eigen::Index Rows, Eigen::Index Cols>
using MaxAlgArray = Eigen::Array<MaxAlg<T>, Rows, Cols>;
using MaxAlgMatrixXd = MaxAlgMatrix<double, Eigen::Dynamic, Eigen::Dynamic>;
using MaxAlgVectorXd = MaxAlgMatrix<double, Eigen::Dynamic, 1>;
using MaxAlgArrayXXd = MaxAlgArray<double, Eigen::Dynamic, Eigen::Dynamic>;
using MaxAlgArrayXd = MaxAlgArray<double, Eigen::Dynamic, 1>;
int main()
{
Eigen::MatrixXd a = Eigen::MatrixXd::Random(10, 10);
Eigen::MatrixXd b = Eigen::MatrixXd::Random(10, 10);
MaxAlgMatrixXd maxalg_a = a.cast<MaxAlg<double> >();
MaxAlgMatrixXd maxalg_b = b.cast<MaxAlg<double> >();
std::cout << (maxalg_a * maxalg_b).cast<double>() << "\n\n";
std::cout << (maxalg_a.array() + maxalg_b.array()).cast<double>() << "\n\n";
std::cout << a.cwiseMax(b) << "\n\n";
}
This disables Eigen's vectorization but the compiler can still do it when you compile with -O3 and it is a lot less work.
I am trying to implement a vector using my own class so I can not do the initialiser list part
# include <iostream>
# include <exception>
# include<initializer_list>
template <class T>
class vector {
public:
T* a;
T n;
int pos, c;
vector() { a = 0; n = 0; }
vector(T n) : n(n) { a = new T[n]; }
vector(std::initializer_list <vector> l) {
a = new T[int(sizeof(l))];
for (int f : l)
*(a + f) = l.begin() + f;
}
void push_back(T k) {
int i = k;
*(a + n) = k;
}
vector& operator= (vector&& th) {
this->a = th.a;
th.a = nullptr; return (*this);
}
vector& operator=(vector& k)
{
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
I am just trying to use pointer offset notation to take the initializer list items into the dynamic array but I get errors VS 17 IDE
Severity Code Description Project File Line Suppression
Error C2440 '=': cannot convert from 'const _Elem *' to 'T'
Error C2440 'initializing': cannot convert from 'const _Elem' to 'int'
Hello Nimrod!
#include <iostream>
#include <exception>
#include <initializer_list>
// normally people don't place a space between '#' and 'include'
template <class T>
class vector {
public:
T* a;
int n;
// probably it is length the vector
// change T to int
int pos, c;
vector() {
a = nullptr;
// do not use '0' to instruct null pointer
n = 0;
}
vector(int n): n(n) { a = new T[n]; }
vector(std::initializer_list<T> l) {
a = new T[l.size()];
// redundant force cast from size_t to int
for (int i = 0; i < l.size(); i++) {
a[i] = l.begin()[i];
}
// for (int f : l) # it seems that you wrote JavaScript before?
// *(a + f) = l.begin() + f;
}
void push_back(T k) {
// assigns "T k" to "int i"? it's confusing
// int i = k;
// *(a + n) = k;
}
// probably still many problems
vector& operator=(vector&& th) {
this->a = th.a;
th.a = nullptr;
return (*this);
}
vector& operator=(vector& k) {
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
You still need more practice. XP
In your context of code, template variable for initializer_list should be T rather than int.
Range for loop with initializer_list<T> will fetch the values
in the list. Therefore it should belong to T.
Custom lambda Comparator slower than normal function c++11. I experienced this a few times. But, Still Couldn't figure out the reason why this is so. Does anyone experience this and know the cause behind it?
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 1;
vector<int> v(N);
vector<int> sorted(N);
map<int, int> counts;
long long start;
void startClock() {
start = clock();
}
void stopClock() {
cout << float( clock () - start ) / CLOCKS_PER_SEC << endl;
}
void copyOriginal() {
for (int i = 0; i < N; ++i)
sorted[i] = v[i];
}
void sortWLambda(map<int, int>& counts) {
cout << "sorting with lambda" << endl;
sort(sorted.begin(), sorted.end(), [counts](const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
});
}
bool comparator(const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
}
void sortWoLambda() {
cout << "sorting w/o lambda" << endl;
sort(sorted.begin(), sorted.end(), comparator);
}
int main() {
for (int i = 0; i < N; ++i) {
int num = rand() % 1234;
counts[num]++;
v[i] = num;
}
copyOriginal();
startClock();
sortWLambda(counts);
stopClock();
copyOriginal();
startClock();
sortWoLambda();
stopClock();
return 0;
}
sorting with lambda 6.28 sec
sorting w/o lambda 0.17 sec
pass by reference made the difference for lambda.
I tried this..
sort(sorted.begin(), sorted.end(), [&counts](const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
});
now this takes same time as normal function
Passing by constant reference in the lambda capture list this helped me too!
Given a horizontal section of wall , and N layers of paints applied from co-ordinates Xi to Yi , Output the distinct number of layers visible.
Here is the problem link http://www.spoj.com/problems/POSTERS/
Here is my solution http://ideone.com/gBJKnL
Approach :
I tried solving the problem by lazily updating child node values through a Segment Tree , the most recent value replaces the older one in their lazy updates. This way only the recent paint gets applied into the horizontal cross-section. although the code works fine on custom test cases , It takes a lot of memory and gets aborted by the Online Judge .
#include <iostream>
#include <set>
#include <vector>
#define MAX 10000000+100
typedef long long int ll;
using namespace std;
ll Tree[3*MAX],lazy[MAX*2];
void Update(ll s,ll start,ll end,ll left,ll right,ll value)
{
if(lazy[s]!=0)
{
Tree[s]=(lazy[s]*(end-start+1));
if(start!=end)lazy[2*s+1]=lazy[s],lazy[s*2+2]=lazy[s];
lazy[s]=0;
}
if(start>end||left>end||right<start)return;
if(start>=left&&end<=right)
{
Tree[s] = (value*(end-start+1));
if(start!=end)
{
lazy[2*s+1]=value;
lazy[2*s+2]=value;
}
return ;
}
ll mid=(start+end)/2;
Update(2*s+1,start,mid,left,right,value);
Update(2*s+2,mid+1,end,left,right,value);
Tree[s] = Tree[s*2+1]+Tree[2*s+2];
}
ll Read(ll s,ll start,ll end,ll left,ll right)
{
if(start>end||start>right||end<left)return 0;
if(lazy[s]!=0)
{
Tree[s]=(lazy[s]*(end-start+1));
if(start!=end)
{
lazy[2*s+1]=lazy[s];
lazy[2*s+2]=lazy[s];
}
lazy[s]=0;
}
if(start>=left&&end<=right)return Tree[s];
else return (Read(2*s+1,start,(start+end)/2,left,right)+Read(2*s+2,1+((start+end)/2),end,left,right));
}
int main() {
// your code goes here
ll t;
cin>>t;
while(t--)
{
ll n,z=1,li=-1;
cin>>n;
vector<pair<ll,ll> > b;
for(ll i=0;i<n;i++)
{
ll u,v;
li = max(li,v);
cin>>u>>v;
b.push_back(make_pair(u-1,v-1));
}
for(auto v: b)
Update(0,0,li+2,v.first,v.second,z++);
set<ll> a;
for(ll i=0;i<li+2;i++)cout<<Read(0,0,li+2,i,i)<<" ",a.insert(Read(0,0,li+2,i,i));
cout<<endl;
cout<<a.size()-1<<endl;
}
return 0;
}
Here is how you should be doing it:
#include <bits/stdc++.h>
#define mx 400005
using namespace std;
int tr[mx], lz[mx];
int t, n, l, r;
void update(int node, int s, int e, int l, int r, int val)
{
if(lz[node]!=0)
{
tr[node]=lz[node];
if(s!=e)
{
lz[node*2]=lz[node];
lz[node*2+1]=lz[node];
}
lz[node]=0;
}
if(s>e || r<s || l>e)
return;
if(s>=l && e<=r)
{
tr[node]=val;
if(s!=e)
{
lz[2*node]=val;
lz[2*node+1]=val;
}
return;
}
int m=s+(e-s)/2;
update(2*node,s,m,l,r,val);
update(2*node+1,m+1,e,l,r,val);
tr[node]=val;
//tr[node]=max(tr[2*node],tr[2*node+1]);
}
int query(int node, int s, int e, int l, int r)
{
if(r<s || e<l)
return 0;
if(lz[node]!=0)
{
tr[node]=lz[node];
if(s!=e)
{
lz[node*2]=lz[node];
lz[node*2+1]=lz[node];
}
lz[node]=0;
}
if(l<=s && r>=e)
return tr[node];
int m=s+(e-s)/2;
return query(2*node,s,m,l,r)+query(2*node+1,m+1,e,l,r);
}
int main()
{
//cout << "Hello world!" << endl;
cin>>t;
while(t--)
{
for(int i=0; i<mx; i++) tr[i]=0;
cin>>n;
int lr[n+1][2];
map<int,bool> mark;
vector<int> vec;
//int c=0;
for(int i=0; i<n; i++)
{
cin>>l>>r;
lr[i][0]=l;
lr[i][1]=r;
if(mark[l]==0)
{
vec.push_back(l);
mark[l]=1;
}
if(mark[r]==0)
{
vec.push_back(r);
mark[r]=1;
}
}
sort(vec.begin(), vec.end());
map<int,int> mp;
int c=1;
for(int i=0; i<vec.size(); i++)
mp[vec[i]]=c++;
for(int i=0; i<n; i++)
{
//cout<<mp[lr[i][0]]<<" "<<mp[lr[i][1]]<<"\n";
update(1,1,vec.size(),mp[lr[i][0]],mp[lr[i][1]],i+1);
}
set<int> ans;
for(int i=1; i<=vec.size(); i++)
{
//cout<<query(1,1,vec.size(),i,i)<<" ";
ans.insert(query(1,1,vec.size(),i,i));
}
int k = ans.size();
if(ans.find(0) != ans.end())
k--;
printf("%d\n",k);
}
return 0;
}
I'm trying to figure out how much the execution time of boost::variant differ from a polymorphism approach. In my first test I got very different results on gcc 4.9.1 and clang+llvm 3.5.
You can find the code below. Here are my results:
clang+llvm
polymorphism: 2.16401
boost::variant: 3.83487
gcc:
polymorphism: 2.46161
boost::variant: 1.33326
I compiled both with -O3.
Is someone able to explain that?
code
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/variant.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <ctime>
struct value_type {
value_type() {}
virtual ~value_type() {}
virtual void inc() = 0;
};
struct int_type : value_type {
int_type() : value_type() {}
virtual ~int_type() {}
void inc() { value += 1; }
private:
int value = 0;
};
struct float_type : value_type {
float_type() : value_type() {}
virtual ~float_type() {}
void inc() { value += 1; }
private:
float value = 0;
};
void dyn_test() {
std::vector<std::unique_ptr<value_type>> v;
for (int i = 0; i < 1024; i++) {
if (i % 2 == 0)
v.emplace_back(new int_type());
else
v.emplace_back(new float_type());
}
for (int i = 0; i < 900000; i++) {
std::for_each(v.begin(), v.end(), [](auto &item) { item->inc(); });
}
}
struct visitor : boost::static_visitor<> {
template <typename T> void operator()(T &item) { item += 1; }
};
using mytype = boost::variant<int, float>;
void static_test() {
std::vector<mytype> v;
for (int i = 0; i < 1024; i++) {
if (i % 2 == 0)
v.emplace_back(0);
else
v.emplace_back(0.f);
}
visitor vi;
for (int i = 0; i < 900000; i++) {
std::for_each(v.begin(), v.end(), boost::apply_visitor(vi));
}
}
template <typename F> double measure(F f) {
clock_t start = clock();
f();
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;
return seconds;
}
int main() {
std::cout << "polymorphism: " << measure([] { dyn_test(); }) << std::endl;
std::cout << "boost::variant: " << measure([] { static_test(); }) << std::endl;
return 0;
}
assembler
gcc
clang+llvm
Clang is known to miscompile some std::vector functions from various Standard libraries, due to some edge cases in their inliner. I don't know if those have been fixed by now but quite possibly not. Since unique_ptr is smaller and simpler than boost::variant it's more likely that it does not trigger these edge cases.
The code you post is practically "Why boost::variant is great". A dynamic allocation and random pointer index in addition to the regular indirections that both perform? That's a heavy hit (relatively).