如何让提升池访问 gsl 矩阵以线程化任务

Posted

技术标签:

【中文标题】如何让提升池访问 gsl 矩阵以线程化任务【英文标题】:How to give boost pool access to a gsl matrix for threading a task 【发布时间】:2020-07-16 23:42:43 【问题描述】:

我有一个 gsl 矩阵,我一遍又一遍地填充它,并且在一个线程上完成所有操作非常繁重。是否可以在 boost pool 线程中修改 gsl 矩阵?

#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;


您需要将以下行添加到您的 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)

感谢您的宝贵时间。

【问题讨论】:

【参考方案1】:

所有线程始终“有权访问”整个进程空间 - 即该进程的内存中的所有对象。

原则上,不需要在进程内“授予 X 访问权限”。

这里:

post(pool, [&_A, &_dostuff]  _dostuff(); ); // post a task to the pool

您过于冗长,这可能表明您的困惑。 _dostuff 已经捕获了矩阵,所以你不需要它。此外,如果您需要捕获 lambda,您可以按值执行(这通常是更安全的默认设置,尤其是在线程化时):

post(pool, [=]  _dostuff(); );

具有讽刺意味的是,您可以简单地将其替换为

post(pool, _dostuff);

为什么它不起作用?

很好用。您的支票中只是有数据竞争 - 所以任何事情都可能发生 (https://en.wikipedia.org/wiki/Undefined_behavior)。

为了获得可靠的检查,您可以先加入线程池:

#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);

打印

20

(也修复了内存泄漏)。

旁注:

您可能希望使用期货来同步任务。另请注意,通过引用捕获指针是不必要的。

【讨论】:

按值传递指针是否会复制任何内容?我通过引用传递速度,但是如果按值传递的指针只是让指针访问矩阵,那么是的,我可以按值传递。你能解释一下吗?谢谢 这是否比通过引用传递指针的计算成本更高?还是您只是在说明它可以被复制和按值传递? 指针复制起来很便宜。引用是......只是引擎盖下的指针(但它们不能为空)

以上是关于如何让提升池访问 gsl 矩阵以线程化任务的主要内容,如果未能解决你的问题,请参考以下文章

线程池的基本概念

如何使用 invokeAll() 让所有线程池完成任务?

如何以抽象函数类型制作线程池任务?

Java面试小短文当任务数超过线程池的核心线程数,如何让它不进入阻塞队列直接启用最大数量的线程去执行任务?

Java面试小短文当任务数超过线程池的核心线程数,如何让它不进入阻塞队列直接启用最大数量的线程去执行任务?

Java面试小短文当任务数超过线程池的核心线程数,如何让它不进入阻塞队列直接启用最大数量的线程去执行任务?