C++线程池 基于C的实现

【C语言和C++】实现线程池 线程,线程池 阅读详情

简介

线程池是什么?

  1. 打饭的阿姨们
  2. 前去吃饭的人们,任务
  3. 管理组件

线程池由三部分组成

  1. 执行队列,线程s
  2. 任务队列,任务s
  3. 管理组件

类似于

  1. 银行营业厅
  2. 食堂打饭
    每个打饭的人都是一个线程
    管理制度

参考链接

C/C++Linux后台服务器开发高级架构师免费学习链接:C/C++Linux服务器开发高级架构师/Linux后台架构师-学习视频

150行代码,手写线程池(B站点赞数观看较多)

线程池解决什么问题

  1. 解决任务处理。
  2. 阻塞IO。
  3. 解决线程创建于销毁的成本问题。
  4. 管理线程。
  5. 异步解耦的作用。

问题

  1. 如何增加线程
  2. 如何减少线程
  3. 增加与减少的策略

C的实现策略

首先我们来认识这些多线程要用的pthread接口函数

pthread_mutex_lock(&pool->jobs_mutex); // 对资源上锁
pthread_mutex_unlock(&pool->jobs_mutex); // 对资源解锁
pthread_cond_signal(&pool->jobs_cond); // 每调用一次,相当于P操作
pthread_cond_wait(&worker->pool->jobs_cond, &worker->pool->jobs_mutex); // 每调用一次相当于V操作
简单来说条件变量就是,许可证的发放,P相当于发了一张许可证,V相当于销毁了一张许可证,当没有许可证的时候pthread_cond_wait函数阻塞

pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void (start_routine) (void *), void *arg);
attr 如果为NULL表示的是默认的属性,start_routine表示函数指针,指向默认的线程函数,arg表示线程函数的唯一的参数
pthread_exit(NULL); // 退出线程,线程销毁操作
线程池实现源代码

C/C++Linux后台服务器开发高级架构师学习视频 点击 linux服务器学习资料 获取,内容知识点包括Linux,Nginx,ZeroMQ,MySQL,Redis,线程池,MongoDB,ZK,Linux内核,CDN,P2P,epoll,Docker,TCP/IP,协程,DPDK等等。免费学习链接:C/C++Linux服务器开发高级架构师/Linux后台架构师-学习视频

code

#include <pthread.h>
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
#include <unistd.h>
#include "timee.hh"
// B 站 线程池
// head insert
#define LL_ADD(item, list) do { \
    item->prev = NULL;          \
    item->next = list;          \
    if(list != NULL)            \
        list->prev = item;      \
    list = item;                \
} while(0)

#define LL_REMOVE(item, list) do { \
    if(item->prev != NULL) item->prev->next = item->next; \
    if(item->next != NULL) item->next->prev = item->prev; \
    if(list == item) list = item->next; \
    item->prev = item->next = NULL; \
} while(0)

struct NWORKER{
    pthread_t thread;
    struct NMANAGER *pool;
    int terminate;
    struct NWORKER *prev;
    struct NWORKER *next;
};

struct NJOB{
    void (*func)(struct NJOB *job);
    void *user_data;
    struct NJOB *prev;
    struct NJOB *next;
};

struct NMANAGER {
    struct NWORKER *workers;
    struct NJOB *jobs;

    pthread_cond_t jobs_cond;
    pthread_mutex_t jobs_mutex;

    int thread_count;
    int count;
    pthread_mutex_t count_mutex;
};

typedef struct NMANAGER nThreadPool;

// static this file is valid
static void *nThreadCallback(void *arg) { 
    struct NWORKER *worker = (struct NWORKER*) arg;
    while(1) {
        pthread_mutex_lock(&worker->pool->jobs_mutex);
        while(worker->pool->jobs == NULL) {
            if(worker->terminate) break;
            // condition wait
            pthread_cond_wait(&worker->pool->jobs_cond, &worker->pool->jobs_mutex);
        }
        if(worker->terminate){
            pthread_mutex_unlock(&worker->pool->jobs_mutex);
            break;
        }
        struct NJOB *job = worker->pool->jobs;
        LL_REMOVE(job, worker->pool->jobs);
        pthread_mutex_unlock(&worker->pool->jobs_mutex);
        job->func((NJOB *)job);
        pthread_mutex_lock(&worker->pool->count_mutex);
        worker->pool->count++;
        pthread_mutex_unlock(&worker->pool->count_mutex);
    }
    free(worker);
    pthread_exit(NULL); 
}

// Thread Pool Create
int nThreadPoolCreate(nThreadPool *pool, int numWorkers) {
    if(numWorkers < 1) numWorkers = 1;
    if(pool == NULL) return -1;
    memset(pool, 0, sizeof(nThreadPool));
    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->jobs_cond, &blank_cond, sizeof(pthread_cond_t));
    pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->jobs_mutex, &blank_mutex, sizeof(pthread_mutex_t));
    memcpy(&pool->count_mutex, &blank_mutex, sizeof(pthread_mutex_t));
    pool->count = 0;
    int i = 0;
    for(i = 0; i<numWorkers; i++){
        struct NWORKER *worker = (struct NWORKER*)malloc(sizeof(struct NWORKER));
        if(worker == NULL) {
            perror("malloc");
            return -2;
        }
        memset(worker, 0, sizeof(struct NWORKER));
        worker->pool = pool;

        int ret = pthread_create(&worker->thread, NULL, nThreadCallback, worker);
        if(ret){
            perror("pthread_create");
            free(worker);
            return -3;
        }
        LL_ADD(worker, pool->workers);
    }
    return 0;
}

// push job to pool 
void nThreadPoolPush(nThreadPool *pool, struct NJOB *job) {
    pthread_mutex_lock(&pool->jobs_mutex);
    
    LL_ADD(job, pool->jobs);
    pthread_cond_signal(&pool->jobs_cond);

    pthread_mutex_unlock(&pool->jobs_mutex);
}

// destroy pool
int nThreadPoolDestroy(nThreadPool *pool){
    struct NWORKER *worker = NULL;
    for(worker = pool->workers; worker != NULL; worker = worker->next) {
        worker->terminate = 1;
    }
    pthread_mutex_lock(&pool->jobs_mutex);
    pthread_cond_broadcast(&pool->jobs_cond);
    pthread_mutex_unlock(&pool->jobs_mutex);
    return 0;
}



#if 1
// 0 --> 1000,
// task --> 
void print(struct NJOB *job) {
    printf("**%d**\n", *(int *)(job->user_data));
    for(int i = 0; i<10000; i++)
        for(int j = 0; j < 10000; j++);
}
int main() {
    Timer<> timer;
    timer.beginStage("START \n");


      
    nThreadPool *pool = new nThreadPool;
    nThreadPoolCreate(pool, 16); // create 16 waiter
    const int M = 100;
    pool->thread_count = M;
    NJOB t[M];
    int num[M];
    for(int i=0; i<M; i++){
        num[i] = i;
    }
    for(int i=0; i < M; i++){
        t[i].func = print;
        t[i].user_data = &num[i];
        nThreadPoolPush(pool, &t[i]);
    }
    // wait all worker finish
    bool check = false;
    while(1){
        pthread_mutex_lock(&pool->count_mutex);
        if(pool->count == pool->thread_count){
            check = true;
        }
        pthread_mutex_unlock(&pool->count_mutex);
        unsigned int microseconds = 1000;
        usleep(microseconds);
        if(check){
            nThreadPoolDestroy(pool);
            break;
        }
    }
    timer.endStage("END \n");
    printf("\n======\n");
}

#endif

timee.hh 计时函数

#pragma once
#include <chrono>
#include <iostream>
using namespace std;
template <typename TimeT = std::chrono::milliseconds>
class Timer{
public:
    Timer() {
        start = std::chrono::system_clock::now();
    }

    size_t value() const {
        auto now = std::chrono::system_clock::now();
        auto duration = std::chrono::duration_cast<TimeT>(now - start);
        return (size_t) duration.count();
    }

    size_t reset() {
        auto now = std::chrono::system_clock::now();
        auto duration = std::chrono::duration_cast<TimeT>(now - start);
        start = now;
        return (size_t) duration.count();
    }

    void beginStage(const std::string &name){
        reset();
        std::cout << name << " .. ";
        std::cout.flush();
    }

    void endStage(const std::string &str = ""){
        std::cout << "done. (took " << value() << " ms";
        if(!str.empty()){
            std::cout << ", " << str;
        }
        std::cout << ")" << std::endl;
    }
private:
    std::chrono::system_clock::time_point start;
};

基于查询法毕竟不太美观

#include <pthread.h>
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
#include "timee.hh"
// Head insert
#define LL_ADD(node, head) do { \
    node->prev = NULL;          \
    node->next = head;          \
    if(head != NULL)            \
        head->prev = node;      \
    head = node;                \
} while(0)

#define LL_REMOVE(node, head) do {                        \
    if(node->prev != NULL) node->prev->next = node->next; \
    if(node->next != NULL) node->next->prev = node->prev; \
    if(head == node) head = node->next;                   \
    node->prev = node->next = NULL;                       \
} while(0)

// 线程列表
struct NWORKER
{
    pthread_t thread;
    struct NMANAGER *pool;
    int terminate;
    struct NWORKER *prev;
    struct NWORKER *next;
};

// 任务列表
struct NJOB
{
    void (*func)(struct NJOB *job);
    void *user_data;
    struct NJOB *prev;
    struct NJOB *next;
};

// 管理器
struct NMANAGER 
{
    struct NWORKER *workers;
    struct NJOB *jobs;

    unsigned int total_jobs;

    unsigned int job_count;        // 任务计数变量
    pthread_mutex_t count_mutex;

    pthread_cond_t end_cond;
    pthread_mutex_t end_mutex;

    pthread_cond_t jobs_cond;
    pthread_mutex_t jobs_mutex;   // 任何一个线程在干活之前都需要先获取锁
};

typedef struct NMANAGER nThreadPool;

// 定义线程所做的工作
static void *nThreadCallback(void *arg) 
{ 
    struct NWORKER *worker = (struct NWORKER*) arg;
    while(1) {
        pthread_mutex_lock(&worker->pool->jobs_mutex);     // 干活之前先获取锁
        while(worker->pool->jobs == NULL) {   // 没有任务
            if(worker->terminate) break;
            // condition wait
            pthread_cond_wait(&worker->pool->jobs_cond, &worker->pool->jobs_mutex);
        }
        if(worker->terminate){
            pthread_mutex_unlock(&worker->pool->jobs_mutex);
            break;
        }
        // 从任务列表获取一个任务进行处理
        struct NJOB *job = worker->pool->jobs;
        LL_REMOVE(job, worker->pool->jobs);
        pthread_mutex_unlock(&worker->pool->jobs_mutex);
        job->func(job);

        pthread_mutex_lock(&worker->pool->count_mutex);
        worker->pool->job_count++;
        if (worker->pool->job_count == worker->pool->total_jobs) {
            pthread_cond_signal(&worker->pool->end_cond);
        }
        pthread_mutex_unlock(&worker->pool->count_mutex);

    }
    free(worker);
    pthread_exit(NULL); 
}

// Thread Pool Create
int nThreadPoolCreate(nThreadPool *pool, int numWorkers) 
{
    if(numWorkers < 1) numWorkers = 1;
    if(pool == NULL) return -1;

    memset(pool, 0, sizeof(nThreadPool));

    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->jobs_cond, &blank_cond, sizeof(pthread_cond_t));
    memcpy(&pool->end_cond, &blank_cond, sizeof(pthread_cond_t));

    pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->jobs_mutex, &blank_mutex, sizeof(pthread_mutex_t));
    memcpy(&pool->count_mutex, &blank_mutex, sizeof(pthread_mutex_t));
    memcpy(&pool->end_mutex, &blank_mutex, sizeof(pthread_mutex_t));


    for(int i = 0; i<numWorkers; i++) {
        struct NWORKER *worker = (struct NWORKER*)malloc(sizeof(struct NWORKER));  // 创建一个线程
        if(worker == NULL) {
            perror("malloc");
            return -2;
        }
        memset(worker, 0, sizeof(struct NWORKER));
        worker->pool = pool;     // 设置管理器

        int ret = pthread_create(&worker->thread, NULL, nThreadCallback, worker);
        if(ret){
            perror("pthread_create");
            free(worker);
            return -3;
        }
        LL_ADD(worker, pool->workers);   // 加入线程列表
    }
    return 0;
}

// push job to pool 
void nThreadPoolPush(nThreadPool *pool, struct NJOB *job) 
{
    pthread_mutex_lock(&pool->jobs_mutex);
    
    LL_ADD(job, pool->jobs);   // 新任务加入任务列表

    pthread_cond_signal(&pool->jobs_cond);   // 唤醒一个线程去处理

    pthread_mutex_unlock(&pool->jobs_mutex); // 释放锁
}

// destroy pool
int nThreadPoolDestroy(nThreadPool *pool)
{
    struct NWORKER *worker = NULL;
    for(worker = pool->workers; worker != NULL; worker = worker->next) {
        worker->terminate = 1;
    }
    pthread_mutex_lock(&pool->jobs_mutex);
    pthread_cond_broadcast(&pool->jobs_cond);
    pthread_mutex_unlock(&pool->jobs_mutex);
    return 0;
}

#if 1

void print(struct NJOB *job) 
{
    printf("**%d**\n", *((int*)job->user_data));
    for (int i = 0; i < 10000; i++)
        for (int j = 0; j < 10000; j++);
}

int main() 
{

    Timer<> timer;
    timer.beginStage("START \n");
    nThreadPool *pool = (nThreadPool *)malloc(sizeof(nThreadPool));
    nThreadPoolCreate(pool, 16); // create 16 worker

#define JOB_COUNT 100

    NJOB t[JOB_COUNT];
    pool->total_jobs = JOB_COUNT;
    pool->job_count = 0;

    for(int i = 0; i < JOB_COUNT; i++) {
        t[i].func = print;
        t[i].user_data = (int *)malloc(sizeof(int));
        (*(int*)t[i].user_data) = i;
        nThreadPoolPush(pool, &t[i]);
    }

    if(pool->job_count != JOB_COUNT) {
        pthread_cond_wait(&pool->end_cond, &pool->end_mutex);
        printf("==>%d\n", pool->job_count);
        nThreadPoolDestroy(pool);
    }
    timer.endStage("END \n");
}

#endif

image

小节

C++的封装对于线程池的实现会更加优雅,但是线程池的C的时间更加粗糙,容易理解。

Linux下分别使用C和C++语言实现线程池(附带源码和解析) 本文记录了分别使用C和C++语言实现线程池的过程,并附带源码和解析。 一、线程池理论知识 1.1什么是线程池 线程池(thread pool): 一种线程使用模式,线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在短时间任务创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数据取决于可用的并发处理器、处理器内核、内存、网络sockets等数量。 因为程序边运行边创建线程是比较耗时的,所以我们通过池化的 阅读详情

相关推荐

用STM32H7的FMC+AD7606搭建多通道数据采集系统:两种工作模式(查询与FIFO中断)的代码详解与性能对比

本文详细解析了基于STM32H7微控制器和AD7606 ADC芯片的多通道数据采集系统设计,重点对比了查询模式与FIFO中断模式的实现方法与性能差异。通过FMC总线实现高速并行数据采集,系统支持16bit同步采样,最高可达200Ksps/通道。文章提供了完整的代码实现和优化策略,帮助工程师在工业监测等实时性要求高的场景中构建可靠的数据采集方案。

weixin_30599769的博客 489

关于线程池原理及相关笔记

如何封装成模块 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <pthread.h> #define LL_ADD(item,list) do { \ item-&g...

jenie的专栏 301

三极管开关电路在脉冲应用中的性能瓶颈分析

深入探讨三极管开关电路在高频脉冲场景下的响应延迟与功耗问题,揭示其性能限制的关键因素。结合实际应用,分析开关速度与信号完整性之间的矛盾,为优化三极管开关电路设计提供实用参考。

weixin_42602368的博客 588

【操作系统-线程池】Pthread 线程池的设计及实现

Lab Week 15 实验报告 实验内容:设计实现一个线程池 (Thread Pool) 使用 Pthread API 管理线程。 利用回调函数作为线程的启动函数。 采用 pthread 信号量解决线程池分配的互斥问题。 讨论上述方案的技术可行性,尝试写一个设计报告。 在一个源代码文件内实现编码、完成编译、运行和用例测试。 I.线程池 线程池的提出,主要是为了解决: (1)频繁地为某一任务创建和销毁线程所引起的系统资源耗费问题; (2)无限制地为并发请求创建线程且系统对线程数量没有限制而引起的系统资源

MaxwellWong 1467

飞控算法-姿态解算之互补滤波

飞控乱入之姿态解算 姿态解算是通过读取各个传感器的数据进行融合最终得到当前飞行器的姿态,姿态通常用Euler角(Roll-Pitch-Yaw)来表示 姿态解算框架 姿态解算的数据源可来自于陀螺仪或加速度计,他们分别都可以得到当前姿态,但实际上他们都有各自的传感器性能的优缺点,需要取长补短,进行数据融合才能得到真实的姿态,这种方法简称 互补滤波 算法 传感器特性 互补滤波 姿态解...

GoolyOh的专栏 1万+

黑猫带你学eMMC协议第14篇:eMMC FFU详解(Field Firmware Update)

1 前言 1.1 声明 本文依据eMMC JEDEC5.1及个人工作经验整理而成,如有错误请留言。 本文结合eMMC JEDEC5.1协议手册查看效果更佳。 1.2 内容提要 1、ffu相关寄存器有哪些? 2、如何设置ffu? 3、什么是ffu?是否能够更新旧版本的固件到emmc? 4、ffu配置流程图。 2 什么是FFU 主机下载新的固件到eMMC,下载成功后eMMC将固件安装到设备。 3 相关寄存器/命令 SUPPORTED_MODES [493] FFU_FEATURES [492] 该

黑猫奥利奥的博客 4660

ThreadPool线程池的C++实现

线程池 threadpool 的C++实现,

墨1024 1893

npm install 时出现npm error code ENOTFOUND和npm error network request to https://registry.npmjs.org的解决方案

本文主要介绍了npm install 时出现npm error code ENOTFOUND和npm error network request to https://registry.npmjs.org 的解决方案,希望能对使用npm的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 6万+

150行代码,手写线程池,每个人都能学会。自行准备linux环境

目录 总结送福利无偿 *1.线程池的使用场景 2. 线程池的实现原理 3. 线程池动态放缩 *日志在罗盘的时候每一次都需要写磁盘,它里面带有缓冲区的,但不一定每次都罗盘,这个过程中间也有一个罗盘动作的不管有没有缓冲区,每执行一次log(level,")都需要写一次磁盘,这个过程中间你会发现写磁盘的速度是很慢的, 对于服务器来说每一次请求,对于有N多个客户端,每个客户端往服务端发送请求 请求一次 我们在服务端这边,把每一次请求,达成日志,打成日志方便我知道代码运行到那个地步,以及错误出在那里,我们可以通过l

qq_44064836的博客 211

SAPGUI 与 ADT 的时代分野:在多云架构下,谁还能代表现代 SAP 开发

摘要(149字) SAP开发工具正经历代际更迭:SAPGUI基于专有协议(NI/DIAG)的厚客户端架构难以适配多云环境,而ADT(ABAP Development Tools)通过HTTP(S)协议和Eclipse生态成为ABAP Cloud/RAP开发的唯一入口。关键差异体现在:ADT支持CDS、行为定义等云原生对象建模,天然对齐BTP的零信任网络;集成ATC、Git等DevOps工具链;而SAPGUI无法创建RAP核心对象,在跨平台、自动化方面存在硬限制。官方文档明确将ADT作为Clean Core战

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 392

【30】软考软件设计师——UML类图与用例图满分精讲|下午第3题常考核心

本文是《软件设计师·50讲通关|从零基础到工程师职称》专栏第30篇,聚焦**模块四:应用技术(下午题)第3道高频大题**,UML建模是历年下午必考核心,单题分值稳定10~12分。全文深度拆解两大核心UML图表:**类图**与**用例图**,超详细讲解类图三层结构、可见性修饰符、五大核心关系(泛化/关联/依赖/聚合/组合)的判定标准与绘图规范;吃透用例图参与者、系统边界、三大关系(包含/扩展/泛化)的底层逻辑,搭配独家**关系秒杀口诀、标准绘图模板、真题改错技巧**;全文适配补图、判断关系、分析场景、纠错优化

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 573

【C/C++】线程池实现

1

IdealSanX的博客 1979

Simulink仿真模块 - Data Type Conversion

Data Type Conversion将输入信号转换为指定的数据类型 在仿真库中的位置为: Simulink / 常用模块 Simulink / Signal Attributes 模型为: 说明 DataTypeConversion模块可将任何 Simulink®数据类型的输入信号转换为您指定的数据类型。 注意 要通过指定模块参数来控制输出数据类型,或者要从下游模块继承数据类型,使用DataTypeConversion模块。要...

jk_101的博客 2521

线程池C和C++语言实现

当并发数很多的时候,并且每个线程执行时间很短的任务,这样就会频繁创建线程,而这样的频繁创建和销毁线程会大大降低系统的执行效率。对于这种场景我们可以使用线程池来复用之前创建的线程,降低线程的频繁创建和销毁工作,达到提高执行效率的目的。

zhqblog的博客 401

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【C/C++】线程池的设计与实现

再服务器的操作系统中,线程是非常珍贵的资源。但是线程的创建和销毁是很消耗资源的,甚至在一些条件下,使用线程的效率还不如不用线程。为了解决这个问题,线程池就产生了。线程池就是指预先创造一组线程的机制,这些预先创建的线程在程序启动的时候就已经准备好,等待执行任务。当有新任务需要执行的时候,线程池会从中分配一个空闲的线程来执行任务,而不是每次都要重新创建和销毁线程。

2403_82787036的博客 811

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

线程池C/C++代码实现

通俗一点来说,任务队列就是一个放任务的地方,当有任务到来的时候,就会唤醒消费者线程来消费任务,管理者线程是用来瘦身或者增容的时候发挥作用的,线程池里面是有一套算法的,基于忙线程数和存活线程数和一些其他的条件来共同进行影响的,这些是管理者线程干的事情,当我们访问公共资源的时候,我们需要进行设置锁,当任务队列的任务数为0或满的时候,我们又需要来设置条件变量,这就是线程池的基本实现原理,具体的还是要看代码的实现,C代码和C++代码实现起来还是有点区别的,代码在下面。线程池就可以提高我们的效率。

2402_84602321的博客 472

深度学习工具包 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")

C/C++手撕线程池(线程池的封装和实现)

此功能是不是画蛇添足有待考证,但是若当我们的工作线程数量不稳定时,频繁调整线程池的线程数量(频繁创建及释放线程)也将导致性能的下降,这种做法理所当然地被我认为是一种本末倒置的做法,而对于线程池中线程的数量,在我做性能测试时考虑到CPU是四核的,就只在线程池中创建了4个线程。这是因为static函数为类的静态函数,当类的成员函数被static修饰后,调用该函数将不会默认传递*this指针,这也是为什么static成员函数中不能使用对象的非static属性:你*this指针都没传我上哪去找你的对象?

az44yao的专栏 613

线程池原理(C和C++实现)

当并发数很多的时候,并且每个线程执行时间很短的任务,这样就会频繁创建线程,而这样的频繁创建和销毁线程会大大降低系统的执行效率。对于这种场景我们可以使用线程池来复用之前创建的线程,降低线程的频繁创建和销毁工作,达到提高执行效率的目的。

子居的博客 1256

C/C++实现线程池、C++20信号量std::counting_semaphore

为了各线程安全访问共享资源,如忙线程数量、当前存活线程数量,需要使用互斥锁,并使用条件变量实现生产者消费者模型。为了管理者能让工作线程自杀,在工作线程阻塞被唤醒后,会对exitNum值进行判断,来决定是否线程自杀。pthread_create创建出一个管理者线程、多个工作线程,并将线程ID存放在数组中。循环读取任务队列,如果没任务了且线程池没关闭,那么就阻塞。为了管理者能够合理对线程数进行调整,需要记录当前当前存活的线程数与忙线程数。只要线程池没关闭,就每隔3秒检测一次,添加或减少工作线程数。

yao-xin 2015

C/C++ 线程池工作原理 & C代码实现

C语言实现线程池,线程池的原理,线程池的结构,C语言改C++

98kaiii的博客 1731

线程池简单实现(C++11/C99)

一、基于C++11的线程池实现 二、基于C99的线程池实现

We choose to go to the moon in this decade and do the other things, not because they are easy, but beacase they are hard. 342

【Linux】多线程 -> 使用C/C++实现简单的线程池

使用C和C++实现了线程池的基本设计......

2202_75924820的博客 1082

C/C++ 线程池简单原理与实现

线程池是用于解决多线程项目中的效率问题的,因此本文将从多线程入手,引出线程池的需求与作用,从而分析其原理与实现。

qq_56031827的博客 1684

《线程界的排班总管 ——C/C++ 线程池从零实现趣味深度指南》

这篇文章通过奶茶店经营的生动类比,系统地讲解了线程池的实现原理和最佳实践。文章首先将多线程编程比作奶茶店运营,指出无节制创建销毁线程的低效性,引出线程池作为解决方案。随后详细拆解了线程池的核心组件和工作流程,并提供了一个基于C++11的完整线程池实现代码,支持任意任务提交和结果获取。文章还包含实用建议:针对CPU密集型和IO密集型任务的不同参数配置、常见陷阱(如线程数过多、队列无上限等),以及通过思维导图归纳的核心知识点。全文以生活化比喻降低理解门槛,同时保持技术深度,是学习多线程编程的优质指南。

c23856的博客 527

【线程池】C++11/C语言实现的简单的线程池

http://www.linuxidc.com/Linux/2013-01/77619.htm 有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池。下面是一个C语言实现的简单的线程池。 头文件: #ifndef THREAD_POOL_H__ #define THREAD_POOL_H__ #include &lt;pthr...

我的笔记本 1335
上一篇: 从开源框架细节的来分析网络模块的封装丨网络模块|Redis|skynet|多线程|单线程|reactor多核实现|IO多路复用
下一篇: 应届生怎么走Linux下C++后台服务器开发路线,工作3-5年的知识体系
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值