I'm currently trying to make my first steps in writing multi-threaded code in CPP and I'm getting a error message that I don't understand at all....
Consider the two functions:
void add_vector(std::vector<int> & vec, int & store){
store = std::accumulate(vec.begin(), vec.end(), 0);
}
int parallel_matrix_sum(std::vector<std::vector<int>> const & mat){
std::vector<std::thread> threads;
std::vector<int> tmp(l);
for (int k =0; k<l; k++){
threads.push_back(std::thread(add_vector, std::cref(mat[k]), std::ref(tmp[k])));
}
for(auto && thread: threads){
thread.join();
}
return std::accumulate(tmp.begin(), tmp.end(), 0);
}
The error I get is
error: attempt to use a deleted function
.
.
.
in instantiation of function template specialization 'std::thread::thread<void (&)(std::vector<int> &, int &), std::reference_wrapper<const std::vector<int>>, std::reference_wrapper<int>, void>' requested here
threads.push_back(std::thread(add_vector, std::cref(mat[k]), std::ref(tmp[k])));
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/type_traits:1916:5: note: '~__nat' has been explicitly marked deleted here
~__nat() = delete;
Upon googling this issue, all the information points to the fact that std::thread needs to copy the arguments, which cannot be done for references.. The suggested solution seems to be to wrap the arguments in a std::ref call. I am already doing this and it is still not working. Does anybody have some suggestions?
I did some playing. I got this to work:
#include <iostream>
#include <thread>
#include <vector>
void add_vector(const int & a, const int & b, int & c) {
c = a + b;
}
int main() {
std::vector<std::thread> threads;
int a = 5;
int b = 10;
int c = 0;
std::cout << "start threads.\n";
threads.push_back(std::thread(add_vector, a, b, std::ref(c) ));
std::cout << "Join.\n";
for (std::thread &thread: threads) {
thread.join();
}
std::cout << "Done. c == " << c << "\n";
}
This is with g++ using --std=c++17.
I updated this with info from Innocent Bystander. Passing by reference can work if you wrap in std::ref() as shown.
I'm going to try a fresh example with vectors.
#include <iostream>
#include <thread>
#include <vector>
void add_vector(const std::vector<int> & vec, int &result) {
result = 0;
for (const int &value: vec) {
result += value;
}
}
int main() {
std::vector<std::thread> threads;
std::vector<int> values;
std::vector<int> results;
values.push_back(10);
values.push_back(15);
results.push_back(0);
std::cout << "start threads.\n";
threads.push_back(std::thread(add_vector, values, std::ref(results[0]) ));
std::cout << "Join.\n";
for (std::thread &thread: threads) {
thread.join();
}
std::cout << "Done. c == " << results[0] << "\n";
}
This above with vector works. I didn't wrap the first args. I did wrap the final one.
The end answer: take a look at the very first argument to your method. It isn't listed as const.
Related
There are tons of answers for sorting a vector of struct in regards to a member variable. That is easy with std::sort and a predicate function, comparing the structs member. Really easy.
But I have a different question. Assume that I have the following struct:
struct Test {
int a{};
int b{};
int toSort{};
};
and a vector of that struct, like for example:
std::vector<Test> tv{ {1,1,9},{2,2,8},{3,3,7},{4,4,6},{5,5,5} };
I do not want to sort the vectors elements, but only the values in the member variable. So the expected output should be equal to:
std::vector<Test> tvSorted{ {1,1,5},{2,2,6},{3,3,7},{4,4,8},{5,5,9} };
I wanted to have the solution to be somehow a generic solution. Then I came up with a (sorry for that) preprocessor-macro-solution. Please see the following example code:
#include <iostream>
#include <vector>
#include <algorithm>
struct Test {
int a{};
int b{};
int toSort{};
};
#define SortSpecial(vec,Struct,Member) \
do { \
std::vector<decltype(Struct::Member)> vt{}; \
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [](const Struct& s) {return s.Member; }); \
std::sort(vt.begin(), vt.end()); \
std::for_each(vec.begin(), vec.end(), [&vt, i = 0U](Struct & s) mutable {s.Member = vt[i++]; }); \
} while (false)
int main()
{
// Define a vector of struct Test
std::vector<Test> tv{ {1,1,9},{2,2,8},{3,3,7},{4,4,6},{5,5,5} };
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
// Call sort macro
SortSpecial(tv, Test, toSort);
std::cout << "\n\nSorted\n";
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
}
Since macros shouldn't be used in C++, here my questions:
1. Is a solution with the algorithm library possible?
2. Or can this be achieved via templates?
To translate your current solution to a template solution is fairly straight forward.
template <typename T, typename ValueType>
void SpecialSort(std::vector<T>& vec, ValueType T::* mPtr) {
std::vector<ValueType> vt;
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [&](const T& s) {return s.*mPtr; });
std::sort(vt.begin(), vt.end());
std::for_each(vec.begin(), vec.end(), [&, i = 0U](T& s) mutable {s.*mPtr = vt[i++]; });
}
And we can call it by passing in the vector and a pointer-to-member.
SpecialSort(tv, &Test::toSort);
Somewhow like this (You just need to duplicate, rename and edit the "switchToShort" funtion for the rest of the variables if you want):
#include <iostream>
#include <vector>
struct Test {
int a{};
int b{};
int toSort{};
};
void switchToShort(Test &a, Test &b) {
if (a.toSort > b.toSort) {
int temp = a.toSort;
a.toSort = b.toSort;
b.toSort = temp;
}
}
//void switchToA(Test& a, Test& b) { ... }
//void switchToB(Test& a, Test& b) { ... }
inline void sortMemeberValues(std::vector<Test>& data, void (*funct)(Test&, Test&)) {
for (int i = 0; i < data.size(); i++) {
for (int j = i + 1; j < data.size(); j++) {
(*funct)(data[i], data[j]);
}
}
}
int main() {
std::vector<Test> tv { { 1, 1, 9 }, { 2, 2, 8 }, { 3,3 ,7 }, { 4, 4, 6 }, { 5, 5, 5} };
sortMemeberValues(tv, switchToShort);
//sortMemeberValues(tv, switchToA);
//sortMemeberValues(tv, switchToB);
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
}
With range-v3 (and soon ranges in C++20), you might simply do:
auto r = tv | ranges::view::transform(&Test::toSort);
std::sort(r.begin(), r.end());
Demo
I was wondering if it possible to create custom functions like for, for_each, while etc.
There's nothing that I want to do that the existing loops won't do it. I am just curious to learn how they work and if I ever need to create my own.
For example if one wants to create another version of the for function that would take only parameter.
In this example, I want to to create a for that only takes one parameter, an integer.
Instead of writing
for (int i = 0; i < 50; ++i)
I would create a for version like this
for_(50)
and they would act the same. How would I do something like that?
I have posted this question in another forum.
In addition to the proposals in other answers, you could create a function like the one below, but it is, at the very end, very similar to using the standard std::for_each.
#include <iostream>
#include <functional>
template<typename C, typename F>
void for_(C begin_, C end_, F&& f) { // [begin_, end_)
for (C i = begin_; i < end_; ++i) {
f(i);
}
}
template<typename C, typename F>
void for_(C count, F&& f) { // special case for [0, count)
for_(0, count, f);
}
void mul2(int x) {
std::cout << x*2 << " ";
}
int main() {
for_(10, [](int i) { std::cout << i << "\n"; });
for_(2, 10, mul2);
}
An ugly and unsafe solution is to use macro:
#define REPEAT(i,N) for(int (i) = 0; (i) < (N); ++(i))
int main()
{
REPEAT(i,10) std::cout << i << std::endl;
return 0;
}
You can't extend the C++ syntax for new loops.
You could use a macro, but this is pretty ugly, and generally best avoided. Another way to get something similar is by passing a functor as a parameter, greatly helped by the introduction of lambda expressions to C++. You can find some examples of such in the <algorithm> header.
For example:
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> numbers = { 1, 4, 5, 7, 10 };
int even_count = 0;
for (auto x : numbers)
{
if (x % 2 == 0)
{
++even_count;
}
}
auto even_count2 = std::count_if(numbers.begin(), numbers.end(), [](int x) { return x % 2 == 0; });
}
You could use a lambda function and pass in a function object as a parameter to be performed for every iteration of the loop.
#include <iostream>
#include <functional>
int main()
{
auto for_ = [](int start, int size, std::function<void (int i)> fn)
{
int end = start + size;
for (int i = start; i < end; ++i)
{
fn(i);
}
};
for_(0, 10, [](int i) { std::cout << i << std::endl; });
for_(0, 10, [](int i) { std::cout << i*2 << std::endl; });
}
It seems like you are reinventing the wheel here a bit. You could just use std::for_each.
However, you could have custom lambda functions that do different things and just implement the operation within the lambda itself without taking in a function object for the operation.
I'm getting my feet wet with Intel TBB and am trying to figure out why I cannot populate a vector passed in by reference to a TBB Task when I also pass in a function by reference.
Here is the code:
// tbbTesting.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "tbb/task.h"
#include <functional>
#include <iostream>
#include <random>
#define NUM_POINTS 10
void myFunc(std::vector<double>& numbers)
{
std::mt19937_64 gen;
std::uniform_real_distribution<double> dis(0.0, 1000.0);
for (size_t i = 0; i < NUM_POINTS; i++)
{
auto val = dis(gen);
std::cout << val << std::endl; //proper values generated
numbers.push_back(val); //why is this failing?
}
std::cout << std::endl;
for (auto i : numbers)
{
std::cout << numbers[i] << std::endl; //garbage values
}
}
class TASK_generateRandomNumbers : public tbb::task
{
public:
TASK_generateRandomNumbers(std::function<void(std::vector<double>&)>& fnc,
std::vector<double>& nums) : _fnc(fnc), _numbers(nums) {}
~TASK_generateRandomNumbers() {};
tbb::task* execute()
{
_fnc(_numbers);
return nullptr;
}
private:
std::function<void(std::vector<double>&)>& _fnc;
std::vector<double>& _numbers;
};
class Manager
{
public:
Manager() { _numbers.reserve(NUM_POINTS); }
~Manager() {}
void GenerateNumbers()
{
_fnc = std::bind(&myFunc, _numbers);
TASK_generateRandomNumbers* t = new(tbb::task::allocate_root())
TASK_generateRandomNumbers(_fnc, _numbers);
tbb::task::spawn_root_and_wait(*t);
}
auto GetNumbers() const { return _numbers; }
private:
std::function<void(std::vector<double>&)> _fnc;
std::vector<double> _numbers;
};
int main()
{
Manager mgr;
mgr.GenerateNumbers();
auto numbers = mgr.GetNumbers(); //returns empty
}
When the execute method performs the operation, I can get values when passing the vector by reference.
When the execute method has to call a function, I get garbage data printed to the console (push_back failing?) and I get an empty container on return.
Can anyone see what I'm missing? Thanks.
I have found a couple of bugs that have nothing to do with tbb.
1) Your myFunc is using range for incorrectly. It does not return an index but each value directly in the vector in turn. Your code is casting each double to an int and using that as index into the array which is why you are gettign garbage.
2) When you use std::bind to create a functor the arguments are copied by value. If you want to pass in a reference then you need to use std::ref to wrap the argument.
If you are using c++11 then you might want to consider using a lambda rather than bind.
I've written a small program using your myFunc in different ways: with and without using std::ref and also a lambda example. You should see that it generates the same numbers 3 times but when it tries to print out v1 it wont contain anything because the generated values were placed in a copy.
#include <vector>
#include <random>
#include <iostream>
#include <functional>
constexpr size_t NUM_POINTS = 10;
void myFunc(std::vector<double>& numbers)
{
std::mt19937_64 gen;
std::uniform_real_distribution<double> dis(0.0, 1000.0);
for (size_t i = 0; i < NUM_POINTS; i++)
{
auto val = dis(gen);
std::cout << val << std::endl; //proper values generated
numbers.push_back(val); //why is this failing? it's not
}
std::cout << std::endl;
}
void printNumbers(std::vector<double>const& numbers)
{
for (auto number : numbers)
{
std::cout << number << std::endl;
}
std::cout << std::endl;
}
int main()
{
std::cout << "generating v1" << std::endl;
std::vector<double> v1;
auto f1 = std::bind(&myFunc, v1);
f1();
printNumbers(v1);
std::cout << "generating v2" << std::endl;
std::vector<double> v2;
auto f2= std::bind(&myFunc, std::ref(v2));
f2();
printNumbers(v2);
std::cout << "generating v3" << std::endl;
std::vector<double> v3;
auto f3 = [&v3]() { myFunc(v3); }; //using a lambda
f3();
printNumbers(v3);
return 0;
}
I have code where I need unique id (packet id for some protocol). So I used std::atomic<int>. After reading documentation I was confused because it stated that increment is done in this way. fetch_add(1)+1
I understand that value inside fetch_add is incremented atomically but I get pre-increment value +1 outside atomic operation. What I would guess is not atomic.
Can I use some_func(++atomic_value)?
I wrote simple code to check if it works. And it works but I don't understand why.
#include<iostream>
#include <atomic>
#include <thread>
#include <vector>
#include <random>
#include <mutex>
#include <algorithm>
std::atomic<int> Index = 0;
//int Index = 0; // non atomic Index. It will generate duplicities
std::vector<int> Numbers;
std::mutex Mutex;
std::default_random_engine Generator;
std::uniform_int_distribution<int> Distribution(5, 10);
void func(int Value)
{
std::lock_guard<std::mutex> Guard(Mutex);
Numbers.push_back(Value);
}
void ThreadProc()
{
Sleep(Distribution(Generator));
func(++Index); // is this proper usage of std::atomic?
}
int main()
{
const int ThreadCount = 1000;
std::vector<std::thread> Threads;
for ( int i = 0; i < ThreadCount; i++ )
{
Threads.push_back(std::thread(ThreadProc));
}
for_each(Threads.begin(), Threads.end(), [](std::thread& t) { t.join(); });
std::sort(Numbers.begin(), Numbers.end());
auto End = std::unique(Numbers.begin(), Numbers.end());
if ( Numbers.end() == End )
{
std::cout << "No duplicites found." << std::endl;
}
else
{
std::cout << "Duplicites found ! - " << Numbers.end() - End << std::endl;
for_each(End, Numbers.end(), [](int n) { std::cout << n << ", "; });
}
return 0;
}
Off-topic question: When I defined Index as non atomic I get duplicities but only from end of range. Numbers are always 900+. Why it is so?
I would like to use an unordered_map as a job or session context object. So, I would like to allocate in some function bundle it with a static function in a function object and send this function object to an io_service. And obviously, I do not worry about deallocating it.
Any ideas on how to do that?
Thank you!
#include <iostream>
#include <unordered_map>
#include "boost/asio.hpp"
#include "boost/thread.hpp"
using namespace std;
namespace asio = boost::asio;
typedef std::unique_ptr<asio::io_service::work> work_ptr;
typedef boost::function<void(void) > boost_void_void_fun;
class job_processor {
public:
job_processor(int threads) : thread_count(threads) {
service = new asio::io_service();
work = new work_ptr(new asio::io_service::work(*(service)));
for (int i = 0; i < this->thread_count; ++i)
workers.create_thread(boost::bind(&asio::io_service::run, service));
}
void post_task(boost_void_void_fun job) {
this->service->post(job);
}
void drain() {
this->work->reset();
}
void wait() {
this->workers.join_all();
}
private:
int thread_count;
work_ptr * work;
asio::io_service* service;
boost::thread_group workers;
};
typedef std::unordered_map<string, unsigned long> map_t;
class with_static_function {
public:
static void print_map(map_t map) {
for(map_t::iterator it = map.begin(); it != map.end(); ++it)
std::cout << it->first << ":" << it->second << std::endl;
}
static void print__heap_map(map_t* map) {
if(!map) return;
for(map_t::iterator it = map->begin(); it != map->end(); ++it)
std::cout << it->first << ":" << it->second << std::endl;
}
};
int main(int argc, char** argv) {
map_t words;
words["one"] = 1;
// pass the reference;
with_static_function::print_map(words);
job_processor *pr = new job_processor(4);
{
map_t* heap_map = new map_t;
(*heap_map)["two"] = 2;
// I need this variable to the job_processor;
// and I do not want to worry about deallocation.
// should happen automatically somehow.
// I am ok with changing the variable to be a shared_ptr or
// anything else that works.
boost_void_void_fun fun = boost::bind(
&with_static_function::print__heap_map,
heap_map);
fun(); // if binding was done right this should have worked.
pr->post_task(fun);
}
pr->drain();
pr->wait();
delete pr;
return 0;
}
A number of observations:
Stop Emulating Java. Do not use new unless you're implementing an ownership primitive (smart handle/pointer type). Specifically, just create a pr:
job_processor pr(4);
Same goes for all the members of job_processor (you were leaking everything, and if job_processor were copied, you'd get double-free Undefined Behaviour
The code
// pass the reference;
with_static_function::print_map(words);
passes by value... meaning the whole map is copied
to avoid that copy, fix the print_map signature:
static void print_map(map_t const& map) {
for(map_t::const_iterator it = map.begin(); it != map.end(); ++it)
std::cout << it->first << ":" << it->second << std::endl;
}
Of course, consider just writing
static void print_map(map_t const& map) {
for(auto& e : map)
std::cout << e.first << ":" << e.second << "\n";
}
The "heap" overload of that could be, as my wording implies, an overload. Be sure to remove the useless duplication of code (!):
static void print_map(map_t const* map) {
if (map) print_map(*map);
}
You don't even need that overload because you can simply use a lambda to bind (instead of boost::bind):
auto heap_map = boost::make_shared<map_t>();
heap_map->insert({{"two", 2}, {"three", 3}});
boost_void_void_fun fun = [heap_map] { with_static_function::print_map(*heap_map); };
Complete working program:
Live On Coliru
#include <iostream>
#include <unordered_map>
#include <boost/asio.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
namespace asio = boost::asio;
typedef boost::function<void(void)> boost_void_void_fun;
class job_processor {
public:
job_processor(int threads) : service(), work(boost::asio::io_service::work(service))
{
for (int i = 0; i < threads; ++i)
workers.create_thread(boost::bind(&asio::io_service::run, &service));
}
void post_task(boost_void_void_fun job) {
service.post(job);
}
void drain() {
work.reset();
}
void wait() {
workers.join_all();
}
private:
asio::io_service service;
boost::optional<asio::io_service::work> work;
boost::thread_group workers;
};
typedef std::unordered_map<std::string, unsigned long> map_t;
namespace with_static_function {
static void print_map(map_t const& map) {
for(auto& e : map)
std::cout << e.first << ":" << e.second << "\n";
}
}
int main() {
// pass the reference;
with_static_function::print_map({ { "one", 1 } });
job_processor pr(4);
{
auto heap_map = boost::make_shared<map_t>();
heap_map->insert({{"two", 2}, {"three", 3}});
boost_void_void_fun fun = [heap_map] { with_static_function::print_map(*heap_map); };
pr.post_task(fun);
}
pr.drain();
pr.wait();
}
Prints
one:1
three:3
two:2