圆周率π的近似计算(三)-MapReduce分布式计算入门_mapreduce计算圆周率

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

进行分布式计算的任务有个先决条件,那就是可以进行并行计算,就是各 map 之间相互独立,无依赖关系.

因此,我们在建立数学模型时最好是一个重复计算无相互关联的模型,而 蒙特卡洛 的模型恰好符合这种特点,因此我们依次构建模型.

在上篇**文章**中,我们采用的通过面积比的方式来近似求解 圆周率 π ,即正方形面积为 1 ,扇形面积为 π/4,则正方形和扇形的面积比为 π/4,求得这个面积比,我们就能得到最后的 π;

蒙特卡罗方法,就是将面积比转化为概率问题求解,就是在正方形中取一随机点进行重复试验,统计出这个点落在扇形中的概率.用这个概率去描述扇形和正方形的面积比,求得概率即可近似求出圆周率 π 的大小;

随机试验的优点是,每次试验相互独立互不影响,缺点随机性大,数据不稳定,一般只用做近似求解.

综上,我们可以将 求解圆周率的任务 转化为随机试验的统计工作.

实现方法
  1. 首先我们给出Mapper阶段方法
public class SolvingPiMapper extends Mapper<LongWritable, Text, Text, Text> {       
    /**
     * key 输入 读取文件的起始位置
     * value 输入 文件中一行的内容
     * context 输出 <k,v>形式
     */
    @Override
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)
            throws IOException, InterruptedException {
        //将从文件中读取的随机试验次数解析出来
        String num = value.toString();
        Integer totle = new Integer(num);
        //声明随机试验中落点在扇形中数量
        int sum = 0;
        //进行随机试验并统计
        for(int i=0;i<totle;i++){
            double x = Math.random();
            double y = Math.random();
            if((x*x+y*y)<1){
                sum++;
            }
        }
        //将最后结果输出
        context.write(new Text("PI"), new Text(totle+"--"+sum));
    }
}

  1. 给出 reduce 方法
public class SolvingPiReducer extends Reducer<Text, Text, Text, DoubleWritable> {
    /**
     * name 输入的 "PI"
     * message 输入的"totle--num"
     * context 输出的<k,v>
     * 所有键位"PI"的输入都用这个方法进行处理
     */
    @Override
    protected void reduce(Text name, Iterable<Text> message, Reducer<Text, Text, Text, DoubleWritable>.Context context)
            throws IOException, InterruptedException {
        //声明试验进行的总数
        long sumTotle =0;
        //声明落点在扇形区域中的总数
        long sumOrder =0;
        //解析输入的message信息,从这提取上述两个值
        for (Text text : message) {
            String[] nums = text.toString().split("--");
            sumTotle+= new Integer(nums[0]);
            sumOrder+= new Integer(nums[1]);
        }
        //System.out.println("π的近似值为"+sumOrder*4.0/sumTotle);
        //输出最后结果
        context.write(name,new DoubleWritable(sumOrder*4.0/sumTotle));
    }
}

解析 map 方法返回的信息,进行汇总并输出最后结果.
3. 定义一个主类,用来描述job并提交job

public class SolvingPiRunner {
    //把业务逻辑相关的信息(哪个是 mapper,哪个是 reducer,要处理的数据在哪里,输出的结果放在哪里……)描述成一个 job 对象
    //把这个描述好的 job 提交给集群去运行
    public static void main(String[] args) throws Exception {
        //用户自定义输入
        System.out.println("请输入你想分的片数:");
        Scanner sc = new Scanner(System.in);
        int pice=new Integer(sc.nextLine());
        System.out.println("请输入你每片执行多少次:");
        String line=sc.nextLine();
        //按照分片生成文件(在实际环境中需要在hdfc中创建文件)
        for(int i=0;i<pice;i++){
            BufferedWriter bw = new BufferedWriter(new FileWriter(new File("D:\\hadoop\\input\\"+(i+1)+".txt")));
            bw.write(line);
            bw.close();
        }

        //把业务逻辑相关的信息(哪个是 mapper,哪个是 reducer,要处理的数据在哪里,输出的结果放在哪里……)描述成一个 job 对象
        //把这个描述好的 job 提交给集群去运行
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        //知道这个job所在jar包
        job.setJarByClass(SolvingPiRunner.class);

        job.setMapperClass(SolvingPiMapper.class);
        job.setReducerClass(SolvingPiReducer.class);
        //设置我们的业务逻辑Mapper类的输出key 和  value 的数据
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        //设置我们的业务逻辑Reducer 类的输出Key和value 的数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(DoubleWritable.class);
        //指定要处理的数据所在的位置
        FileInputFormat.setInputPaths(job, "D:\\hadoop\\input\\*.txt");
        //指定处理完成后,结果所保存的位置
        FileOutputFormat.setOutputPath(job, new Path("D:\\hadoop\\output\\result"));
        //向yarn集群提交这个job

        boolean res = job.waitForCompletion(true);
        System.exit(res?0:1);
    }
}

在windows环境下模拟集群环境执行测试;

遇到的问题
  • 启动问题报错
Exception in thread "main" java.io.IOException: (null) entry in command string: null chmod 0700 D:\tmp\hadoop-lxc\mapred\staging\lxc1332581434\.staging
        at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:773)
        at org.apache.hadoop.util.Shell.execCommand(Shell.java:869)
        at org.apache.hadoop.util.Shell.execCommand(Shell.java:852)
        at org.apache.hadoop.fs.RawLocalFileSystem.setPermission(RawLocalFileSystem.java:733)
        at org.apache.hadoop.fs.RawLocalFileSystem.mkOneDirWithMode(RawLocalFileSystem.java:491)
        at org.apache.hadoop.fs.RawLocalFileSystem.mkdirsWithOptionalPermission(RawLocalFileSystem.java:532)
        at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:509)
        at org.apache.hadoop.fs.FilterFileSystem.mkdirs(FilterFileSystem.java:312)
        at org.apache.hadoop.mapreduce.JobSubmissionFiles.getStagingDir(JobSubmissionFiles.java:133)
        at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:144)
        at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1290)
        at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1287)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:422)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1746)
        at org.apache.hadoop.mapreduce.Job.submit(Job.java:1287)
        at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:1308)
        at test.demo.SolvingPiRunner.main(SolvingPiRunner.java:54)

解决方法

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

阶课程,涵盖了95%以上大数据知识点,真正体系化!**

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值