随机森林算法的加速:OpenMP方法

news2024/11/26 18:32:14

使用OpenMP加速随机森林

    • 前言
    • 使用OpenMP
    • 对RF训练的加速
      • 代码
      • 加速效果
    • 对特征重要性评估的加速
      • 代码
    • 加速效果
    • 附录
      • Windows中使用OpenMP
      • Linux中使用OpenMP

项目主页:randomforest
C++ implementation of random forests classification, regression, proximity and variable importance.
推荐阅读:

  1. Random Forests C++实现:细节,使用与实验
  2. 随机森林特征重要性(Variable importance)评估方法
  3. 随机森林Proximity实现及应用

前言

  OpenMP用于编写多线程应用程序的 API。它是一组编译器指令和库例程,使并行编程比使用显式线程更容易它实际上大大简化了用 Fortran 、C/ C++ 编写多线程编程程序。主流编译器(gcc/g++,Visual C++)都支持OpenMP,在Windows和Linux操作系统上都比较容易上手,对原始代码的侵入较少。
  随机森林由N棵随机树(Randomized Trees)组成,在训练与其他衍生算法中,很多情形下每棵树内的运算是独立的,且与树的顺序无关。因此,可以采用OpenMP进行加速,将对随机树的运算分配到多个线程中,然后由CPU的多核进行并行处理。主要采用OpenMP对for循环加速功能,将顺序执行的循环并行化,大大提升了算法整体速度。下面的章节介绍了OpenMP在随机森林加速中的应用,也对OpenMP的使用方法进行简单解释。主要分为对随机森林训练算法的加速、对预测算法的加速、对Proximity的加速以及对特征重要性算法的加速给出了具体的实验结果。

使用OpenMP

对RF训练的加速

代码

随机森林训练其中每棵随机数是独立的过程,所以很容易采用OpenMP对训练每棵随机树的循环进行并行化。

#include "omp.h"
... ...
int TrainRandomForestClassifierOMP(float **data, int *label, RandomCForests_info RFinfo, LoquatCForest *&loquatForest, int jobs, int trace)
{
    ... ...
    jobs = jobs>omp_get_max_threads() ? omp_get_max_threads() : jobs;
	omp_set_num_threads(jobs);
	int growed_num = 0;
	... ...
#pragma omp parallel for 
	for (int i = 0; i < Ntrees; i++)
	{
		GrowRandomizedCLoquatTreeRecursively(data, label, RFinfo, loquatForest->loquatTrees[i]);
		#pragma omp critical  
		{
			growed_num++;
			if (trace > 0 && growed_num % trace == 0)
			{
				cout << "Tree: " << growed_num << endl;
			}
		}
	}
	... ...
	return 0;
}

omp_set_num_threads 设置了线程数量,如果线程数<=CPU核心数,那么每个线程可以又一个独立核心处理,所以这个线程数应该设置为CPU核心数或更少;
#pragma omp parallel for 对紧跟其后的for循环进行多核并行加速;
#pragma omp critical 指定后面大括号里的代码块同一时间只能被一条线程执行的代码区域,为了是统计到目前为止有多少颗随机树完成训练。

加速效果

实验平台为:Intel i5-13400F(10核), win11操作系统
对不同数据集进行训练,记录原始算法实现(without OpenMP)、4线程 (With OpenMP T=4)与8线程 (With OpenMP T=8) 加速,三种情况下的训练耗时。

数据集 (样本数)参数Without OpenMP (秒)With OpenMP T=4 (秒)With OpenMP T=8 (秒)
mnist (60000)[200, 27*, 40, 2]97.327.616.843
pendigits (7494)[200,4*, 40, 2]1.8690.5270.309
MAGIC_Gamma_Telescope (19020)[200,3*, 40, 2]9.0662.5541.464
Sensorless_drive_diagnosis (58509)[200,6*, 40, 2]50.0213.897.91

理想情况下,4线程和8线程应该分别为原始算法耗时的 1 4 \frac {1}{4} 41 1 8 \frac {1}{8} 81。从实验结果来看,加速倍数与理论接近,考虑到线程调度等也需要耗时,所以实际并没有达到理论倍数是正常的。

对特征重要性评估的加速

特征重要性的实现请见:随机森林特征重要性(Variable importance)评估方法

代码

#pragma omp parallel for 
for (tr = 0; tr < Ntrees; tr++)
{
	struct LoquatCTreeStruct* pTree = loquatForest->loquatTrees[tr];
	int *pIndex = pTree->outofbag_samples_index;
	int oobnum = pTree->outofbag_samples_num;

	if (pIndex == NULL || oobnum == 0)
		continue;
	oobFound = true;
	oobOfTrees[tr] = oobnum;
	int* permuted_order = new int[oobnum];

	int index, predicted_class_index;
	float confidence = 0.f;
	int correct_num = 0, correct_num_premute = 0;
	int i = 0;
	for (; i < oobnum; i++)
	{
		index = pIndex[i];
		PredictAnTestSampleOnOneTree(data[index], variables_num, pTree, predicted_class_index, confidence);
		if (predicted_class_index == label[index])
			correct_num++;
	}

	float* tmp_data = new float[variables_num];
	for (int var = 0; var < variables_num; var++)
	{
		// permuting (var)th variables
		// permute [0, oobnum-1]
		permute(oobnum, permuted_order);

		for (correct_num_premute = 0, i = 0; i < oobnum; i++)
		{
			index = pIndex[permuted_order[i]];
			memcpy(tmp_data, data[pIndex[i]], variables_num * sizeof(float));
			tmp_data[var] = data[index][var];
			PredictAnTestSampleOnOneTree(tmp_data, variables_num, pTree, predicted_class_index, confidence);
			if (predicted_class_index == label[pIndex[i]])
				correct_num_premute++;
		}

		DeltMatrix[tr][var] = correct_num - correct_num_premute;
		mean_var[var] += (correct_num - correct_num_premute) / (float)oobOfTrees[tr];
	}

	delete [] permuted_order;
	delete [] tmp_data;
}

与训练加速的方法相同,也是通过for循环的并行化进行加速。与原始代码相比,OpenMP版本的代码将循环内要用到的变量都在循环内部定义,这样每个循环就有一份独立的变量,并行时不会造成冲突。

加速效果

数据集 (样本数,特征数)参数Without OpenMP (秒)With OpenMP T=4 (秒)With OpenMP T=8 (秒)
mnist (60000,720)[200, 27*, 40, 2]958947201681
pendigits (7494,16)[200,4*, 40, 2]1.3640.4300.323
MAGIC_Gamma_Telescope (19020,10)[200,3*, 40, 2]17.064.8062.965
Sensorless_drive_diagnosis (58509,48)[200,6*, 40, 2]915.83261.02156.57

附录

Windows中使用OpenMP

Visual studio中开启openmp的方法见下图
在这里插入图片描述
开启OpenMP后多核处理的截图如下
在这里插入图片描述

Linux中使用OpenMP

编译时增加命令 -fopenmp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1169404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【德哥说库系列】-Oracle 19C PDB创建大全

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

双绞线(寻线仪,测线仪),光纤测试工具(红光笔,OTDR,光功率计)

网络测试方式&#xff1a; 根据测试中是否向被测网络注入测试流量&#xff0c;可以将网络测试方法分为主动测试和被动测试。 主动测试&#xff1a;利用测试工具有目的地主动问被测网络注入测试流量&#xff0c;根据测试流量的传送情况分析网络技术参数。优点是具备良好的灵活…

读程序员的制胜技笔记03_有用的反模式(上)

1. 教条 1.1. 一成不变的法则 1.2. 这些东西会遮蔽我们的双眼&#xff0c;你坚持相信的时间越久&#xff0c;你被遮蔽双眼的程度也就越深 2. 质疑所有教给你的东西 2.1. 它们有多么有用 2.2. 使用它们的理由 2.3. 使用它们的好处 2.4. 使用它们的代价 3. 反模式 3.1. …

13、Kubernetes核心技术 - Ingress

目录 一、概述 二、Ingress工作原理 三、Ingress 使用 3.1)、Ingress-http方式 3.1.1)、创建Ingress Controller和对应的Service 3.1.2)、创建tomcat的Pod和Service 3.1.3)、创建nginx的Pod和Service 3.1.4)、创建ingress http代理 3.1.5)、配置本地host文件 3.1.6)、…

基于STM32设计的室内环境监测系统(华为云IOT)_2023

一、设计需求 基于STM32+华为云物联网平台设计一个室内环境监测系统,以STM32系列单片机为主控器件,采集室内温湿度、空气质量、光照强度等环境参数,将采集的数据结果在本地通过LCD屏幕显示,同时上传到华为云平台并将上传的数据在Android移动端能够实时显示、查看。 【1…

更新版PHP神算网八字算命星座解梦周易占卜程序源码/PC+H5移动端整站适配/PHP源码带手机版

源码简介&#xff1a; 这个是更新版PHP神算网八字算命星座解梦周易占卜程序源码&#xff0c;能够在PCH5移动端整站适配。作为H5付费算命PHP源码&#xff0c;八字算命网站源码&#xff0c;功能很多强大实用。 2023.3 更新记录&#xff1a; 1、更新了23年属相信息&#xff1b;…

12 pinctrl 和 gpio 子系统

一、pinctrl 子系统 1. 什么是 pinctrl 子系统&#xff1f; 首先回顾一下如何初始化 LED 所使用的 GPIO&#xff1a; ①、修改设备树&#xff0c;添加相应的节点&#xff0c;节点里面重点是设置 reg 属性&#xff0c; reg 属性包括了 GPIO相关寄存器。 ②、获取 reg 属性中 …

基于顺序表实现的可存储性通讯录!!!

基于顺序表实现的通讯录 通讯录的基本功能 顺序表顺序表的部分变量修改修改处一修改处二修改处三 头文件 Contact.h通讯录自定义结构体 功能实现 源文件 Contact.c读取文件中联系人的信息 void ContactReadFile(contact* pcon)保存到文件 void ContactSave(contact* pcon) 测试…

Python:知道什么叫类吗,我这人实在不知道啥叫累。Python类的定义和使用。

前言 在 python 中&#xff0c;对于相同类型的对象进行分类&#xff0c;抽象后&#xff0c;得出共同的特征而形成了类&#xff08;class&#xff09;&#xff0c;面向对象程序设计的关键就是如何合理地定义这些类并且组织多个类之间的关系。 创建类时用变量形式表示对象特征的…

ChinaSoft 论坛巡礼|开源软件供应链论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

Python基础之列表、元组和字典

一文拿捏Python基本数据类型“列表、数组和字典” 引言 Python中的 列表(英文叫list) 、 元组(英文叫tuple)和字典&#xff08;dictionary&#xff09; 也是 序列 特性的&#xff0c;它们也是非常常用的数据类型。 1、列表&#xff08;List&#xff09; 01、概述 列表&#…

【黑马程序员】SSM框架——SSM整合

文章目录 前言一、SSM 整合1. SSM 整合思路1.1 Spring 整合 MyBatis配置模型数据层标准开发业务层标准开发测试接口事务处理 1.2 Spring 整合 SpringMVCweb 配置类SpringMVC 配置类基于 Restful 的 Controller 开发 2. SSM 整合具体实现2.1 创建工程2.2 SSM 整合SpringMyBatisS…

forward和完美转发

std::move(value)是独立于值的右值引用&#xff0c;一个右值引用参数作为函数的形参&#xff0c;在函数内部再转发该参数的时候已经变成了一个左值&#xff0c;并不是它原来的类型了。 template<typename T> void forwardValue(T& val) {processValue(value); //…

基于STC12C5A60S2系列1T 8051单片机A/D转换器应用

基于STC12C5A60S2系列1T 8051单片机A/D转换器应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍STC12C5A60S2系列1T 8051单片机A/D转换器介绍STC12C5A60S2系列1T 805…

算法题:870. 优势洗牌

该算法是临时想出来的&#xff0c;Java代码的实现在时间上不占优&#xff0c;之后有时间要优化一下&#xff0c;目前就是给大家提供一下思路。 解题思路&#xff1a;田忌赛马的思想 贪心法。 Step1. 对两个数组进行排序。 Step2. 同时遍历排序后的nums2和nums1&#xff0c;将…

RAM和ROM的区别(详解)

RAM和ROM的区别 RAM&#xff08;随机存取存储器&#xff09;和ROM&#xff08;只读存储器&#xff09;都是计算机中常见的存储器类型&#xff0c;它们在计算机系统中有不同的作用和特性。 RAM&#xff08;随机存取存储器&#xff09;&#xff1a; 作用&#xff1a; 用于临时存储…

鸿蒙LiteOs读源码教程+向LiteOS中添加一个简单的基于线程运行时的短作业优先调度策略

一、鸿蒙Liteos读源码教程 鸿蒙的源码是放在openharmony文件夹下&#xff0c;openharmony下的kernel文件夹存放操作系统内核的相关代码和实现。 内核是操作系统的核心部分&#xff0c;所以像负责&#xff1a;资源管理、任务调度、内存管理、设备驱动、进程通信的源码都可以在…

利用maven的dependency插件将项目依赖从maven仓库中拷贝到一个指定的位置

https://maven.apache.org/plugins/maven-dependency-plugin/copy-dependencies-mojo.html 利用dependency:copy-dependencies可以将项目的依赖从maven仓库中拷贝到一个指定的位置。 使用默认配置拷贝依赖 如果直接执行mvn dependency:copy-dependencies&#xff0c;是将项目…

解决方案中word中分页符的使用

在投标方案中要善于使用“分页符”&#xff0c;尽可能少使用分节符号&#xff0c;没有分页符前&#xff0c;你每次修改你的标书或者文件&#xff0c;增加或者修改内容后。你的格式字段前后都是会发生变化&#xff0c;如何稳定的保证结构呢&#xff0c;那就是分页符的使用&#…

如何提高Python图像表格数据提取的准确率?

Python图像表格数据提取 1、数据来源2、目标图像3、图像文本提取4、图像灰度化与二值化可以提高识别准确率吗1、数据来源 国家统计局:http://www.stats.gov.cn/sj/ 数据来源:国家统计局中国统计年鉴2022年人口数及构成 2、目标图像 数据(部分)如下: 数据形式:http://www…