I have a gsl matrix that I'm filling over and over again and its pretty heavy to do it all on one thread. Is it possible to modify a gsl matrix in a boost pool thread?
#include <gsl/gsl_linalg.h>
#include <boost/asio.hpp>
int main() {
int SIZE = 3; // small size
gsl_matrix * _A = gsl_matrix_alloc(SIZE, SIZE); // set the gsl matrix to 3x3
gsl_matrix_set_all(_A, 0); // make them all 0 to provide contrast if value changes
auto _dostuff = [&_A]() {
gsl_matrix_set (_A, 0, 0, 20); // set the (0, 0) position to 20
};
boost::asio::thread_pool pool(1); // open up a thread pool containing 1 thread
boost::asio::post(pool, [&_A, &_dostuff]{_dostuff() ;}); // post a task to the pool
std::cout << gsl_matrix_get (_A, 0, 0) << std::endl; // check to see if the (0, 0) position is 20 (its not)
return 0;
}
You will need to add the following lines to your Cmake
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++17 -pthread")
find_package(GSL REQUIRED)
target_link_libraries(<folder name> GSL::gsl GSL::gslcblas)
Thank you for your time.
All threads always "have access" to the entire process space - i.e. all objects in the memory for that process.
In principle, nothing is required to "give X access" within the process.
Here:
post(pool, [&_A, &_dostuff] { _dostuff(); }); // post a task to the pool
you are overly verbose, which might indicate your confusion. _dostuff
already captures the matrix, so you don't need that. Also, if you needed to capture the lambda you could do so by value (which is generally a safer default especially when threading):
post(pool, [=] { _dostuff(); });
Ironically, you could simply replace it with
post(pool, _dostuff);
Well it works. You just have a data race in your check - so anything can happen (https://en.wikipedia.org/wiki/Undefined_behavior).
To get a reliable check you might join the thread pool first:
#include <boost/asio.hpp>
#include <gsl/gsl_linalg.h>
#include <iostream>
namespace ba = boost::asio;
int main() {
int SIZE = 3; // small size
gsl_matrix* _A = gsl_matrix_alloc(SIZE, SIZE); // 3x3
gsl_matrix_set_all(_A, 0); // zero for reference
auto _dostuff = [_A]() {
gsl_matrix_set(_A, 0, 0, 20); // set (0, 0) to 20
};
ba::thread_pool pool(1); // one thread
post(pool, _dostuff); // post task
pool.join();
std::cout
<< gsl_matrix_get(_A, 0, 0)
<< std::endl;
gsl_matrix_free(_A);
}
Prints
20
(also fixed the memory leak).
You might want to use futures to synchronize on tasks. Also note that capturing the pointer by reference is unnecessary.