C++ 异步编程探索(一) task链式调度 -- future CONTINUATION

Boost AISO官方教程翻译版 Boost Asio 官方文档翻译 阅读详情

同步Vs异步编程, 一直是大家讨论的热点。 同步编程以其逻辑简单,受到了一些对时间不敏感的程序青睐,而异步编程以其高效深受处女座程序员喜爱。

作为一只处女座程序猿,当然要异步异步异步。。。

说到异步, C++11之前, 用的最多的就是各种callback function。举个例子, 假如你是一个老板,告诉自己的秘书把文件打印出来,打完了送给我。然后你就可以干别的活,等打印好了,秘书会到你的办公室给你文件,你就可以继续处理文件。

在这里打印文件就是我们设置的callback function。 等文件打印完成这个事件发生,秘书就会带着文件给你。也就是调用你的callback function。秘书可能就是你新启动的线程。

同步编程就是你自己去打印文件,等文件打印完了再干其它的事情。

显然异步编程更有效率,但是现在有几个问题:

问题一 : 秘书怎么把打印完的文件交给你。可能现实中很简单,但是在编程中就涉及到线程之间通信,线程间通知机制,这个以后在说。

问题二 : 人类的思维是同步的,连续的,由于引入太多的callback function。这会打断人类的思维。

下面就讨论第二个问题。

第一种解决方法是最近很火的名词“协程”当然不是那个携程。GO语言把这个概念带火了,它的思想就是线程的调度开销太大,所以在线程里又起了很多轻量级的“线程”,也就是“协程”。线程自己调度,无非是存下当前的各种寄存器信息后执行其它程序,完事后在将之前存的东西在还原,继续执行, 但是C语言并不像GO语言这种天生自带“携程”,确实有很多框架比如boost::croroutine微信也开源了一套。 有了携程就可以按照人类的思维,一步一步的执行想干的活,协程的痛点是如何处理“阻塞”程序,比如socket,I/O等等。对于协程,还是持观望态度。
下面写一个小例子,看看封装后的协程写异步程序是多么爽的一件事,至于为什么爽是因为同步编程才是符合人类的思维习惯的。以前设置异步读取操作后,数据的处理都必须在回调函数中处理,现在可以直接在异步操作后接着处理啦!

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <string>
#include <ctime>
#include <iostream>
#include <boost/enable_shared_from_this.hpp>

using namespace boost::asio;
using std::cerr;
using std::endl;

io_service io_service_;

class session : public boost::enable_shared_from_this<session>
{
  public:
    explicit session(ip::tcp::socket socket) : sock_(std::move(socket)),
                                               strand_(io_service_),
                                               uuid_(std::rand())
    {
    }

    ~session() { cerr << "~sessoin ->" << uuid_ << endl; }

    void go()
    {
        auto self(shared_from_this());
        boost::asio::spawn(strand_,
                           boost::bind(&session::do_echo, self, _1));
    }

    void do_echo(yield_context yield)
    {
        char data[128];
        std::size_t n = sock_.async_read_some(boost::asio::buffer(data), yield);
        cerr << "RECVED:【" << data << "】->" << uuid_ << endl;
        std::time_t now = std::time(nullptr);
        std::string time_str = std::ctime(&now);
        async_write(sock_, buffer(time_str), yield);
        sock_.shutdown(ip::tcp::socket::shutdown_send);
    }

  private:
    ip::tcp::socket sock_;
    io_service::strand strand_;
    std::size_t uuid_;
};

void start_accept(yield_context yield)
{
    ip::tcp::acceptor acceptor(io_service_, ip::tcp::endpoint(ip::tcp::v4(), 2016));

    for (;;)
    {
        boost::system::error_code ec;
        ip::tcp::socket socket(io_service_);

        acceptor.async_accept(socket, yield[ec]);
        if (!ec)
            boost::make_shared<session>(std::move(socket))->go();
    }
}

int main(int argc, char *argv[])
{
    boost::asio::spawn(io_service_, start_accept);
    io_service_.run();
}

编译命令g++ -std=c++11 test.cpp -lboost_system -lboost_coroutine -lboost_context -o test
其实,感觉现实中协程更多的是对编程方式的改变,对控制流的操控可以用同步的结构写出异步的效果,但是协程是用户态的而不是原生的多线程,所以并不能并行执行提高并发率。但是协程能够在各个协程间进行高效的切换,这一点可以做到比传统依赖于异步调度的效率更高,这才体现出协作的本质吧!
第二种:
C++11中引入了一个新的东东 std::future,有个这个就可以让你设置一个工作,然后在需要结果时调用get()拿到你想要的值。

前面说了,人类的思维是连续的,同步的。所以人类更适应连续的链式调用,比如告诉秘书打印一份文件然后把文件交给XXX。

也就是future .then()

可是令人失望的是future.then()作为候选并没有进入C++17,而是进入了std::experimental。

https://en.cppreference.com/w/cpp/experimental/future/then

不过还好我们有boost这个神器。

下面我们尝试一下:

#include <iostream>
#include <string>
#define BOOST_THREAD_VERSION 4

#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION

#include <boost/thread/future.hpp>
#include <stdio.h>

using namespace boost;

int main()
{
    future<int> f1 = async([]() { return 123; });

    future<std::string> f2 = f1.then([](future<int> f) {
                                   std::cout << f.get() << std::endl; // here .get() won't block
                                   return std::string("sgfsdfs");
                               })
                                 .then([](future<std::string> f) {
                                     std::cout << f.get() << std::endl;
                                     return std::string("sgfsdfs");
                                 })
                                 .then([](future<std::string> f) {
                                     std::cout << f.get() << std::endl;
                                     return std::string("sgfsdfs");
                                 });
    getchar();
}

这里要吐槽一下, 首先编译命令g++ then.cpp -std=c++11 -lboost_system -lboost_thread官方网站只是写了一些例子,完全不能编译, 首先你要设置版本信息,要不然编译不过#define BOOST_THREAD_VERSION 4应该2以上就行,还要定义一些宏#define BOOST_THREAD_PROVIDES_FUTURE
要用then还要定义下边的宏
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION

编译问题解决后,是不是很爽?完全不用考虑是哪个线程干的工作, 只要then then then,活就干完了。

通过GDB 看了一下运行流程,发现每个then都会起一个新的线程。 首先起线程很耗资源。其次还有个线程安全的问题。所以这种task适合task之间没有依赖的工作。

为了解决这个问题很多大厂已经有相应的解决方案,例如微软的PPL
https://msdn.microsoft.com/en-us/library/dd492418.aspx
在linux下阉割版pplx
https://github.com/Microsoft/cpprestsdk/wiki/Programming-with-Tasks
intel有TBB
https://www.threadingbuildingblocks.org/tutorial-intel-tbb-task-based-programming

他们都有完善的task schedule 功能。但是都不是标准的实现。

现在我的想法是实现和std::promise&&std::future类似的功能,future有then也就是有continuation功能。
同时为了解决线程间数数据问题,将scheule功能用boost::asio实现,所有task都schedule到一个thread(后续到多个thread类似boost::srand)

有机会实现这个想法。

完

c++11多线程编程(十):packaged_task<>介绍与实例 本节讨论c++11中std::packaged_task的特性与使用方法 std::packaged_task std::packaged_task是一个类模板,代表一个异步任务。封装了 1、可调用实体,即函数,lambda函数或函数对象 2、一个共享状态,通过关联的回调来存储返回的值或抛出的异常。 假设我们有一个现有的函数从数据库中提取数据并返回, //从DB获取数据 std 阅读详情

相关推荐

C++异步编程实战:std::async与std::future核心用法详解

异步编程是现代软件开发中提升程序响应性和资源利用率的核心技术,其原理在于将耗时操作交由后台执行,避免阻塞主线程。在C++中,标准库提供了基于多线程的异步编程模型,通过任务分解与结果回调机制实现并发执行。这一技术的工程价值在于简化并发逻辑,充分利用多核CPU性能,尤其适用于计算密集型任务和I/O密集型场景中的性能优化。C++11引入的std::async与std::future组件构成了轻量级异步方案的基础,其中std::async作为任务启动器支持异步与延迟执行策略,而std::future则作为结果凭证,

weixin_33946020的博客 357

探究C++20协程(3)——通用异步任务Task的简单设计

其中,Result 的模板参数 T 对应于 Task 的返回值类型。有了这个结果类型就可以很方便地在需要读取结果的时候调用 get_or_throw。Promise type 是一个协程的基础结构,它定义了协程的返回类型、如何初始化和结束协程,以及协程在遇到 co_await、co_yield、和 co_return 时的行为。初始化和最终挂起:在协程开始执行前,会创建一个 promise 对象。当协程结束或最终挂起时,通过 promise 对象来清理和收尾。

一枚菜鸡 2209

C++异步编程利器:std::packaged_task原理、应用与线程池实战

在C++并发编程中,异步任务执行与结果获取是核心需求。其基本原理是通过分离任务执行与结果同步,实现高效、安全的并行计算。std::future/std::promise机制为此提供了标准解决方案,允许一个线程承诺(promise)在未来提供结果,而另一个线程通过future等待并获取该结果,这构成了C++11以来基于任务的异步编程范式的基础技术价值。该模式极大地简化了线程间通信与同步的复杂度,避免了手动管理锁和条件变量的繁琐与易错性。其典型应用场景包括计算密集型任务的后台执行、GUI应用中的耗时操作不阻塞主

www.itmmd.com 327

Boost.Asio spawn 的用法

Boost.Asio spawn 的用法 官方文档例子 void go() { auto self(shared_from_this()); //使用spawn开启协程 boost::asio::spawn(strand_, [this, self](boost::asio::yield_context yield) {...

weixin_44048823的博客 4284

C++20协程重构分布式通信:告别回调地狱,实现高性能异步编程

在分布式系统与高并发编程中,异步IO是处理海量连接与复杂网络交互的核心技术。传统基于回调或Future/Promise的方案虽然性能出色,但常导致代码逻辑碎片化、可维护性差,形成所谓的“回调地狱”。C++20引入的协程(Coroutines)作为一种无栈协程模型,通过挂起与恢复机制,允许开发者以同步的代码风格编写异步逻辑,从根本上改善了代码结构。其技术价值在于将底层异步事件驱动与上层顺序逻辑解耦,大幅提升开发效率与代码可读性。在工程实践中,结合事件循环与自定义调度器,协程可高效管理网络IO、RPC调用、连接

dianzongfan5428的博客 487

基于C++的task 类

C++, task 类;线程库;

【C++异步编程终极指南】:深度剖析std::future链式组合的底层机制

掌握C++26 std::future链式组合操作,轻松构建高效异步任务流。适用于网络请求串联、多阶段数据处理等场景,通过then、when_all等方法实现无阻塞组合,提升并发性能。底层机制深度解析,助你写出更优雅的异步代码,值得收藏。

ByteShoal的博客 630

群晖NAS变身私有Git服务器:DS218+部署与TortoiseGit客户端实战指南

本文详细介绍了如何将群晖NAS(如DS218+)变身为私有Git服务器,并配置TortoiseGit客户端实现高效代码管理。通过硬件检查、系统更新、Git Server套件安装及权限配置等步骤,帮助开发者在局域网内搭建安全、高速的代码托管环境,特别适合小团队协作。

weixin_29252171的博客 224

C++异步编程核心:packaged_task::get_future机制与高性能应用实践

异步编程是现代高性能系统设计的核心概念,旨在解决同步阻塞导致的资源浪费和响应延迟问题。其基本原理是通过任务解耦,让主线程在发起耗时操作后能继续执行其他工作,待结果就绪后再处理,从而提升系统吞吐量和响应性。C++标准库提供的std::packaged_task与std::future是实现这一模式的关键技术组件,它们共同构成了类型安全、标准化的异步结果传递机制。其中,packaged_task::get_future接口是连接任务执行与结果获取的核心纽带,它通过共享状态模型将任务承诺与未来结果绑定,确保了数据

weixin_34195364的博客 402

CentOS8安装NVIDIA显卡驱动、CUDA和Anaconda

CentOS8安装NVIDIA显卡驱动和CUDA 参考:CentOS nvidia+cuda+cudnn 安装 安装英伟达显卡驱动 1、检查是否安装了NVIDIA的GPU(硬件层面): lspci | grep -i nvidia 2、安装GCC、kernal组件、dkms等 sudo yum install gcc sudo yum install gcc-c++ sudo yum -y install kernel-devel sudo yum -y install kernel-headers s

智慧的旋风的博客 1万+

远程桌面(RDP)共享USB设备全攻略:不止Hyper-V,你的加密狗和CH340串口也能远程用

本文详细介绍了远程桌面(RDP)共享USB设备的完整解决方案,包括加密狗和CH340串口设备的远程使用技巧。通过RemoteFX USB重定向技术,用户可以在远程会话中无缝使用本地USB设备,提升工作效率。文章涵盖企业级配置、典型设备实战案例及高级故障排除方法,是远程工作者的实用指南。

weixin_42522964的博客 334

HPX异步编程完全指南:掌握future和数据流同步的艺术

在当今高性能计算领域,**HPX异步编程**已成为并行与并发编程的黄金标准。HPX作为C++并行与并发标准库,通过先进的**future机制**和**数据流同步**技术,让开发者能够充分利用现代多核处理器的计算能力。无论你是刚接触并行编程的新手,还是寻求优化现有代码的资深开发者,本指南都将为你揭开HPX异步编程的神秘面纱,帮助你掌握构建高效、可扩展并行应用的艺术。 ## HPX异步编程核心概念解

gitblog_00678的博客 432

STM32F103 RTC闹钟唤醒Stop模式的EXTI17中断实现

本文详细介绍了STM32F103如何通过RTC闹钟触发EXTI17中断实现从Stop模式的高效唤醒。针对低功耗应用场景,提供了完整的硬件配置、CubeMX设置及代码实现方案,包括时间格式转换、中断处理和功耗优化技巧,帮助开发者可靠实现定时唤醒功能。

ol78901234的博客 231

【std::future链式组合进阶指南】:掌握高效异步编程的5大核心技巧

掌握高效异步编程的5大核心技巧,深入解析std::future链式组合的应用场景与实现原理,涵盖连续任务编排、异常传递、then扩展设计等关键方法,提升代码响应速度与可维护性,进阶指南值得收藏。

ProceChat的博客 352

win10系统下使用Mask_Rcnn训练自己的数据

版权所有,翻版必究。https://mp.youkuaiyun.com/console/editor/html/106094147 运行环境:WIN10,pycharm,相应的CUDA,CUDNN,tensorflow1.15.0,tensorflow-gpu-1.14.0,Anaconda3 第一步:Mask RCNN开源项目:https://github.com/matterport/Mask_RCNN 第一步:数据准备 首先安装labelme进行数据的标注。安装方法pip install labe

fightingxyz的博客 1750

STM32F103C8T6实战指南:从零搭建最小系统与GPIO控制

本文详细介绍了STM32F103C8T6微控制器的实战应用,从零开始讲解如何搭建最小系统并进行GPIO控制。内容涵盖电源电路设计、时钟配置、GPIO工作模式详解及实战项目开发,帮助初学者快速掌握这款ARM Cortex-M3内核微控制器的核心开发技能,适用于物联网设备和嵌入式系统开发。

lemon的博客 632

C++异步编程三剑客:std::async、future与promise实战指南

并发编程是现代软件开发中提升性能的核心技术,其核心原理在于通过多线程或多进程同时执行任务,以充分利用多核CPU的计算能力。在C++中,传统的线程与锁机制虽然功能强大,但直接操作往往带来数据竞争、死锁等复杂问题,代码可维护性较差。为此,C++11标准引入了更高层次的异步编程抽象,即std::async、std::future和std::promise,它们共同构成了管理异步任务和数据流的核心工具集。这些组件的技术价值在于将开发者从繁琐的线程同步细节中解放出来,转向以数据为中心的“生产者-消费者”模型,从而编写

weixin_33754065的博客 715

超详细!DeepSeek本地搭建部署、搭建知识库及智能体教程

通过以上详细的步骤,我们完成了DeepSeek的本地搭建部署、知识库的搭建以及智能体的创建。这一过程不仅让我们深入了解了大模型的应用,还为我们开发个性化的智能应用奠定了基础。在实际应用中,可以根据具体需求进一步优化模型、知识库和智能体的性能和功能。希望本文能帮助大家快速上手DeepSeek相关技术,开启属于自己的人工智能创新之旅。

Ljugg的博客 8187

C++23前必学的future扩展方案(彻底解决链式回调困境)

彻底解决异步编程回调困境,详解std::future链式组合实现方案。涵盖C++23前的扩展方法、适用场景与then/when等核心接口设计,提升代码可读性与维护性。掌握高效异步流程控制,值得收藏。

IterStream的博客 442

5.4 GTT BO的内存分配分析

本文分析了AMD GPU驱动中的GTT技术实现。GTT作为GPU页表,负责管理主机内存与GPU虚拟地址的映射,支持大容量内存访问和统一寻址。文章详细介绍了GTT的核心数据结构amdgpu_gtt_mgr、初始化流程,以及BO(Buffer Object)创建时GTT区间的分配与释放机制。GTT管理通过TTM框架实现分层设计,提供内存统计、兼容性检查等接口,并支持动态迁移、多进程隔离等高级特性。该机制为AMD GPU提供了高效灵活的内存管理基础。

图形/计算GPU的驱动与虚拟化技术分享园地 3738

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

std::future链式组合性能优化:3种提升响应速度的关键方法

掌握std::future链式组合性能优化技巧,显著提升异步任务响应速度。适用于高并发场景,通过延迟执行、避免阻塞调用和合理调度三种方法优化资源利用。有效减少线程争用,提高程序吞吐量,值得收藏。

VarFlow的博客 180

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

基于 Ceres Solver 的 3D 位姿图优化实战:pose_graph_3d 示例全面解析

本文围绕 Ceres Solver 官方示例 `pose_graph_3d`(位于 `src/third_party/ceres-solver/examples/slam/pose_graph_3d/`),系统讲解如何使用 Ceres 的非线性最小二乘框架求解三维 SLAM 中的位姿图优化问题:从 g2o 数据格式的定义、Eigen 四元数与 Ceres 旋转表示的区别,到残差项(cost fun

gitblog_01067的博客 166

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C++20协程实战:从异步编程痛点解析到生成器与Task实现

异步编程是现代软件开发中处理高并发I/O操作的核心范式,旨在提升程序响应能力与资源利用率。其原理在于通过非阻塞操作与事件循环,避免线程等待,从而高效管理大量并发任务。这项技术的核心价值在于能够以同步的代码风格编写异步逻辑,大幅提升代码可读性与可维护性。在服务器开发、网络编程及高性能计算等场景中,异步编程尤为重要。C++20引入的语言级协程(Coroutines)正是这一领域的重大革新,它通过`co_await`、`co_yield`等关键字,以及**协程帧(Coroutine Frame)**、**承诺类型

weixin_34357928的博客 350

Folly与C++20协程集成:构建高性能异步C++服务

异步编程是现代高性能服务开发的核心技术,旨在解决海量并发连接与复杂I/O操作带来的性能瓶颈。其原理在于通过非阻塞调用和事件驱动模型,避免线程等待,从而提升系统吞吐量。在C++生态中,Facebook开源的Folly库提供了成熟的异步基础设施,如Future和执行器,是构建可靠后端服务的基石。C++20标准引入的原生协程支持,则提供了以同步代码风格编写异步逻辑的语法糖,显著提升了代码可读性与可维护性。将两者结合,即利用Folly久经考验的异步运行时驱动C++20协程,能够在工程实践中实现既简洁又高效的并发处理

352

C++20协程promise_type深度解析:从原理到工业级Task实现

协程作为现代异步编程的核心概念,通过挂起与恢复的执行机制,实现了高效的并发控制。其原理在于将函数状态保存于堆分配的协程帧中,而非传统调用栈,从而支持非阻塞的异步操作。这一技术价值在于显著提升I/O密集型应用的吞吐量,并简化回调地狱问题,广泛应用于网络服务器、游戏引擎、数据流处理等场景。在C++20协程框架下,promise_type作为协程内部状态与外部调用的关键桥梁,决定了协程的创建、调度、数据传递与生命周期管理。本文通过实现一个支持链式调用与异常处理的Task模板,深入剖析promise_type在协程

weixin_34405354的博客 290

Gamdl 手把手教程:用 Wrapper 完成 Apple Music ALAC 无损下载

Apple Music 的本地缓存导不出来,网页端最高也只听得到 AAC 256kbps——想要 ALAC 无损文件存进自己的曲库,一直很难。Gamdl 是一款 Python 命令行工具,配合 Wrapper 中间服务就能开启 Apple Music 的 ALAC 无损下载通道,最高支持 24bit/192kHz,下载完的专辑自动整理好目录、标签和封面。这篇教程带你从零敲出命令,完成第一张 ALA

gitblog_00483的博客 474
上一篇: boost log -- 使用心得和碰到的那些坑(二)
下一篇: C++ 异步编程探索(二) thread safe
Max_Cong
博客等级 码龄10年 281粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值