C多线程编程- 近似求解π
本程序使用蒙特卡洛方法估算圆周率(π)。它首先创建了指定数量的线程,每个线程生成一个随机点并检查该点是否在单位圆内。基于这些线程的结果,程序计算在单位圆内的点的比例,并乘以4来估算π的值。为了对比,程序还直接在主线程中(没有并发)进行了相同的π估算过程(由于每次都是生成随机数,所以这个基准也没啥意义hh~)。最后,程序打印出两种方法得到的π值。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>struct arg_t {float x;float y;
};void *start(void *arg) {struct arg_t *ll = (struct arg_t *)arg;float x1 = ll->x;float y1 = ll->y;long M = 0;if (x1*x1 + y1*y1 <= 1.0) {M ++;}pthread_exit((void *)M);
}int main(int argc, char **argv) {if (argc < 2) {fprintf(stderr, "Please provide a number as an argument.\n");exit(1);}long N1 = atol(argv[1]);// printf("%ld\n", N1);pthread_t tids[N1];// pai(concurrency)for (long i = 0; i < N1; ++ i) {struct arg_t *arg = malloc(sizeof(struct arg_t));int x = rand();int y = rand();arg->x = 1.0*x / RAND_MAX;arg->y = 1.0*y / RAND_MAX;pthread_create(&tids[i], 0, start, arg);}void *res = 0;long M = 0;for (long i = 0; i < N1; ++ i) {pthread_join(tids[i], &res);M += (long)res;}printf("pai = %f\n", 4.0*M/N1); // concurrency// pai(oracle)M = 0;for (long i = 0; i < N1; ++ i) {int x = rand();int y = rand();float x1 = 1.0*x / RAND_MAX;float y1 = 1.0*y / RAND_MAX;if (x1*x1 + y1*y1 <= 1.0) {M ++;}}printf("pai = %f\n", 4.0*M/N1); // oraclepthread_exit(0);
}
测试一下上述程序:
majn@tiger:~$ ./pai 10000
pai = 3.171200
pai = 3.142000
majn@tiger:~$ ./pai 100000
Segmentation fault (core dumped)
分析Segmentation fault的原因:
在上面的程序中,为每个线程都动态分配了 arg_t 结构的内存,但在线程执行完毕后,这些内存并没有被释放。虽然这不是立即的问题,但长期这样会导致内存泄露。应该在线程函数中或 pthread_join 之后释放这些内存。
改进方案:
一种方法是在线程函数 start 的结尾释放它(插个眼hh~)。但由于在主函数中可能还需要访问这些结构,更安全的方法是在 pthread_join 之后释放这些动态分配的内存。
修改上述代码:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>struct arg_t {float x;float y;
};void *start(void *arg) {struct arg_t *ll = (struct arg_t *)arg;float x1 = ll->x;float y1 = ll->y;long M = 0;if (x1*x1 + y1*y1 <= 1.0) {M ++;}pthread_exit((void *)M);
}int main(int argc, char **argv) {if (argc < 2) {fprintf(stderr, "Please provide a number as an argument.\n");exit(1);}long N1 = atol(argv[1]);struct arg_t *args[N1];// printf("%ld\n", N1);pthread_t tids[N1];// pai(concurrency)for (long i = 0; i < N1; ++ i) {args[i] = malloc(sizeof(*args[i]));// struct arg_t *arg = malloc(sizeof(*arg));int x = rand();int y = rand();args[i]->x = 1.0*x / RAND_MAX;args[i]->y = 1.0*y / RAND_MAX;pthread_create(&tids[i], 0, start, args[i]);}void *res = 0;long M = 0;for (long i = 0; i < N1; ++ i) {pthread_join(tids[i], &res);M += (long)res;free(args[i]);}printf("pai = %f\n", 4.0*M/N1); // concurrency// pai(oracle)M = 0;for (long i = 0; i < N1; ++ i) {int x = rand();int y = rand();float x1 = 1.0*x / RAND_MAX;float y1 = 1.0*y / RAND_MAX;if (x1*x1 + y1*y1 <= 1.0) {M ++;}}printf("pai = %f\n", 4.0*M/N1); // oraclepthread_exit(0);
}
这样,每次线程执行完毕并被主线程收回后,对应的动态分配的内存都会被释放。
测试一下修改后的程序:
majn@tiger:~$ ./pai 100000
pai = 3.721760
pai = 3.137640
majn@tiger:~$ ./pai 1000000
Segmentation fault (core dumped)
好好好,这样玩儿是吧。
分析Segmentation fault的原因:
仔细观察上面的程序,我使用了一个固定大小的线程数组:pthread_t tids[N1];。对于大的 N1 值,这可能会导致栈溢出。在大多数系统上,默认的栈大小可能不足以容纳大量的 pthread_t 变量。
改进方案:
考虑动态分配线程ID数组的空间。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>struct arg_t {float x;float y;
};void *start(void *arg) {struct arg_t *ll = (struct arg_t *)arg;float x1 = ll->x;float y1 = ll->y;long M = 0;if (x1*x1 + y1*y1 <= 1.0) {M ++;}pthread_exit((void *)M);
}int main(int argc, char **argv) {if (argc < 2) {fprintf(stderr, "Please provide a number as an argument.\n");exit(1);}long N1 = atol(argv[1]);struct arg_t *args[N1];// printf("%ld\n", N1);pthread_t *tids = malloc(N1 * sizeof(pthread_t));// pai(concurrency)for (long i = 0; i < N1; ++ i) {args[i] = malloc(sizeof(*args[i]));// struct arg_t *arg = malloc(sizeof(*arg));int x = rand();int y = rand();args[i]->x = 1.0*x / RAND_MAX;args[i]->y = 1.0*y / RAND_MAX;pthread_create(&tids[i], 0, start, args[i]);}void *res = 0;long M = 0;for (long i = 0; i < N1; ++ i) {pthread_join(tids[i], &res);M += (long)res;free(args[i]);}printf("pai = %f\n", 4.0*M/N1); // concurrency// pai(oracle)M = 0;for (long i = 0; i < N1; ++ i) {int x = rand();int y = rand();float x1 = 1.0*x / RAND_MAX;float y1 = 1.0*y / RAND_MAX;if (x1*x1 + y1*y1 <= 1.0) {M ++;}}printf("pai = %f\n", 4.0*M/N1); // oraclepthread_exit(0);
}
majn@tiger:~$ ./pai 1000000
pai = 3.972176
pai = 3.142136
majn@tiger:~$ ./pai 10000000
Segmentation fault (core dumped)
???不玩儿了!!! 到此为止,我们把输入数据的规模N1从一开始最大接受10000扩大到现在最大接受1000000。
彩蛋: 要不然把为每个线程都动态分配的 arg_t 结构在线程函数 start 的结尾释放试一试?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>struct arg_t {float x;float y;
};void *start(void *arg) {struct arg_t *ll = (struct arg_t *)arg;float x1 = ll->x;float y1 = ll->y;long M = 0;if (x1*x1 + y1*y1 <= 1.0) {M ++;}free(arg);pthread_exit((void *)M);
}int main(int argc, char **argv) {if (argc < 2) {fprintf(stderr, "Please provide a number as an argument.\n");exit(1);}long N1 = atol(argv[1]);// printf("%ld\n", N1);// pthread_t tids[N1];pthread_t *tids = malloc(N1 * sizeof(pthread_t));// pi(concurrency)for (long i = 0; i < N1; ++ i) {struct arg_t *arg = malloc(sizeof(struct arg_t));int x = rand();int y = rand();arg->x = 1.0*x / RAND_MAX;arg->y = 1.0*y / RAND_MAX;pthread_create(&tids[i], 0, start, arg);}void *res;long M = 0;for (long i = 0; i < N1; ++ i) {pthread_join(tids[i], &res);M += (long)res;}printf("pai = %f\n", 4.0*M/N1); // concurrency// pi(oracle)M = 0;for (long i = 0; i < N1; ++ i) {int x = rand();int y = rand();float x1 = 1.0*x / RAND_MAX;float y1 = 1.0*y / RAND_MAX;if (x1*x1 + y1*y1 <= 1.0) {M ++;}}printf("pai = %f\n", 4.0*M/N1); // oraclepthread_exit(0);
}
majn@tiger:~$ ./pai_init 10000000
pai = 3.997218
pai = 3.141381
majn@tiger:~$ ./pai_init 100000000
pai = 3.999722
pai = 3.141420
majn@tiger:~$ ./pai_init 1000000000
^C // 时间太长了,不想等了
Amazing!!!怎么这么神奇?
注: 蒙特卡洛方法(Monte Carlo method)是一种通过随机抽样来获得数值解的统计方法。这个方法得名于摩纳哥的蒙特卡洛赌场,因为它大量使用随机性和概率。蒙特卡洛方法在物理学、工程学、经济学和许多其他领域都有广泛的应用。
关键概念和特点:
-
随机抽样:这是蒙特卡洛方法的核心。为了得到一个问题的数值解,这个方法使用随机数或更通常地说,使用伪随机数。
-
统计结果:通过对大量的随机样本进行统计分析,得到的是一个近似解,而不是确切的解。
-
精度与样本数量:通常,随着样本数量的增加,估算的精度也会提高。但是,为了使误差减少到原来的一半,样本数通常需要增加四倍。
-
应用:蒙特卡洛方法在多种应用中都非常有用,尤其是在问题的解析解很难得到或者不存在时。例如,它被用于估算复杂积分、求解难以解析的统计物理问题、进行金融市场模拟等。
-
示例 - 估算π:一个经典的应用是使用蒙特卡洛方法估算π的值。方法是这样的:随机投掷点到单位正方形内,统计落在单位圆内的点的数量。落在圆内的点数与总点数的比例,乘以4,就给出了π的近似值。
简而言之,蒙特卡洛方法是一种利用随机性来求解问题的技术,通过对大量样本的统计分析来获得结果。
相关文章:
C多线程编程- 近似求解π
本程序使用蒙特卡洛方法估算圆周率(π)。它首先创建了指定数量的线程,每个线程生成一个随机点并检查该点是否在单位圆内。基于这些线程的结果,程序计算在单位圆内的点的比例,并乘以4来估算π的值。为了对比,…...
YOLOV7量化第二步: 模型标定
2.模型标定 当然可以,模型量化中的标定(calibration)是一个关键过程,它主要确保在降低计算精度以减少模型大小和提高推理速度的同时,不会显著损害模型的准确性。现在,我将根据您提供的步骤解释这一过程。 …...
前端-uniapp-开发指南
美团外卖微信小程序开发 uniapp-美团外卖微信小程序开发P1 成果展示P2外卖小程序后端,学习给小程序写http接口P3 主界面配置P4 首页组件拆分P13 外卖列表布局筛选组件商家 布局测试数据创建样式 请求商家外卖数据封装请求并发请求 uni-app框架调用https接口 开发小程…...
Java集合类ArrayList的应用-杨辉三角的前n行
目录 一、题目 杨辉三角 二、题解 三、代码 四、总结 一、题目 题目链接:https://leetcode.cn/problems/pascals-triangle/description/ 杨辉三角 题目描述:给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨…...
C语言-函数
函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() 。 主函数可以调用其他函数,其他函数也可以相互调用,用户也可以那个自定义函数。 函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实…...
蓝桥杯 枚举算法 (c++)
枚举就是根据提出的问题,——列出该问题的所有可能的解,并在逐一列出的过程中,检验每个可能解是否是问题的真正解, 如果是就采纳这个解,如果不是就继续判断下一个。 枚举法一般比较直观,容易理解࿰…...
Wordpress自定义小工具logo调用设置(可视化)
在主题开发中,需要调用网站的logo,最简单的办法就是用wp自带的函数,那就是the_custom_logo(),使用它还可以通过后台-自定义-logo,边修改边预览,还是很香的。 自定义徽标支持应首先使用add_theme_support()添…...
面试常考数据结构:红黑树、B树、B+树各自适用的场景
1. 磁盘基础知识 分页: 现代操作系统都使用虚拟内存来印射到物理内存,内存大小有限且价格昂贵,所以数据的持久化是在磁盘上。虚拟内存、物理内存、磁盘都使用页作为内存读取的最小单位。一般一页为4KB(8个扇区,每个扇…...
Paddle GPU版本需要安装CUDA、CUDNN
完整的教程 深度学习环境配置:linuxwindows系统下的显卡驱动、Anaconda、Pytorch&Paddle、cuda&cudnn的安装与说明 - 知乎这篇文档的内容是尽量将深度学习环境配置(使用GPU)所需要的内容做一些说明,由于笔者只在windows和linux下操作过…...
MYSQL length函数
mysql length函数计算结果的单位是啥,和varchar字段类型的单位是相同的吗? 做了一下实验,结果如下: 1.mysql length 函数计算的是有多少个字符,比如字段值是 permission 则length函数计算结果为10。 2.如果字段类型是…...
uniapp 在android手机上运行tab栏页面跳转问题
【问题描述】: 使用uniapp写的项目,在tab页面,无论使用哪种方式的跳转,只要是在url后面拼接参数,在打包成apk文件后,在手机上面安装使用,都是获取不到susIndex参数的,而在浏览器上面…...
css3 hover效果
CSS3中的:hover伪类用于创建鼠标悬停时的样式效果。当用户将鼠标悬停在页面元素上时,你可以为这些元素定义不同的样式规则,以实现交互效果 /* 一般样式规则 */ element {/* 正常状态下的样式 */ }/* 悬停样式规则 */ element:hover {/* 鼠标悬停时的样式…...
C语言char与short取反以及符号判断问题
这个问题主要是在从对一个变量进行符号判断引出,有一种判断方法是#define ISUNSIGNED(Value) (Value >0 && ~Value >0) 主要是通过将符号位取反然后将变量与0进行比较。传入int与unsigned int结果正确,但是当传入unsigned char 与unsign…...
Gpt-4多模态功能强势上线,景联文科技多模态数据采集标注服务等您来体验!
就在上个月,OpenAI 宣布对ChatGPT 进行重大更新,该模型不仅能够通过文字输入进行识别和分析,还能够通过语音、图像甚至视频等多种模态的输入来获取、识别、分析和输出信息。这一重要技术突破,将促进多模态自然语言处理的发展&…...
【idea】 java: 找不到符号
idea 启动时提示 java: 找不到符号 java: 找不到符号 符号: 方法 getCompanyDisputeCount() 位置: 类型为com.yang.entity.AreaAnalyse的变量 areaAnalyse 在setting ——> Compiler ——>Shared build process VM options: 添加: -Djps.track.ap.dep…...
Flink测试利器之DataGen初探 | 京东云技术团队
什么是 Flinksql Flink SQL 是基于 Apache Calcite 的 SQL 解析器和优化器构建的,支持ANSI SQL 标准,允许使用标准的 SQL 语句来处理流式和批处理数据。通过 Flink SQL,可以以声明式的方式描述数据处理逻辑,而无需编写显式的代码…...
linux更换常用软件的默认缓存路径(.conda, .huggingface等)
在使用linux的过程中,我们往往会使用软件安装很多packages,其中的大多数软件(例如conda)会把当前安装的packages缓存起来,以加速之后的相同package的安装。 而很多软件的默认缓存路径是user自己的home路径。下面罗列几…...
Kafka消费者使用案例
本文代码链接:https://download.csdn.net/download/shangjg03/88422633 1.消费者和消费者群组 在 Kafka 中,消费者通常是消费者群组的一部分,多个消费者群组共同读取同一个主题时,彼此之间互不影响。Kafka 之所以要引入消费者群组…...
SpringMVC全注解开发
在学习过程中,框架给我们最大的作用,就是想让开发人员尽可能地只将精力放在具体业务功能的实现之上,而对于各种映射关系的配置,统统由框架来进行完成,由此,注解就很好的将映射功能进行实现,并且…...
解决 android Cannot access ‘<init>‘: it is private in
最近要在2个非直接依赖module使用单例,有一种注入依赖的方式可以,但是报了如下错误: Cannot access <init>: it is private in 经过查阅资料,原来是依赖的单例类的构造函数不能使用private,这里做个记录&#…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
