美文网首页Python学习日志程序员
【第十五天】函数式与并行运算

【第十五天】函数式与并行运算

作者: 人生苦短_我用Python | 来源:发表于2018-03-27 13:41 被阅读8次

第七章 函数式编程

7.1

1.Python中的函数式

函数式编程强调了函数的纯粹性(purity)
一个纯函数是没有副作用的(Side Effect),即这个函数的运行不会影响其他函数
为了达到纯函数标准,函数式编程要求其变量都是不可变更的

py并非完全的函数式编程语言,在py中,存在着可变更的对象,也能写出非纯函数
但如果我们借鉴函数式编程,尽量在编程中避免副作用,就会有许多好处
由于纯函数相互独立,我们不必担心函数调用对其他函数的影响
所以使用起来更加简单,另外,纯函数也方便进行并行化运算
在并行化编程时,我们经常担心不同进程之间相互干扰的问题
当多个进程同时修改一个变量时,进程的先后顺序会影响最终结果
如下面两个函数:

from threading import Thread
 
x = 5
 
def double():
    global x
    x = x*2

def plus_ten():
    global x
    x = x + 10

thread1 = Thread(target=double)
thread2 = Thread(target=plus_ten)
thread1.start()
thread2.start()
thread1.join()
thread2.join()

print(x) 
20

上面两个函数中使用了关键字global
global说明了x是一个全局变量
函数对全局变量的修改能被其他函数看到,因此也有副作用
如果两个进程并行地执行两个函数,函数的执行顺序不确定
则结果可能是double()中的x = x*2先执行,最终结果为20
也有可能是plus_ten()中的x = x + 10先执行,最终结果为30
这被称为竞跑条件(Race Condition),是并行编程中需要极力避免的

from threading import Thread
 
x = 5
 
def double():
    global x
    x = x*2

def plus_ten():
    global x
    x = x + 10

thread1 = Thread(target=double)
thread2 = Thread(target=plus_ten)
thread2.start()
thread1.start()
thread1.join()
thread2.join()

print(x) 
30

函数式编程消灭了副作用,即无形中消除了竞跑条件的可能性
因此,函数式编程天生适用于并行化运算

2.并行运算

上一节中,我们已经涉及到并行运算,所谓并行运算,是指多条指令同时执行
一般来说,一台单处理器计算机同一时间只能执行一条指令
这种每次执行一条指令的工作方式称为串行运算

大规模并行运算通常是在有多个主机组成的集群(Cluster)上进行的
主机之间可以借助高速的网络设备通信,一个集群造价不菲
然而,我们可以在单机上通过多进程或多线程的方式
模拟多主机的并行处理,即使一台单机中,也往往存在着多个运行中的程序
即所谓的进程,例如:我们在打开浏览器上网的同时
还可以流畅的听音乐,这给我们一个感觉,计算机在并行的进行上网和放音乐两个任务
事实上,单机的处理器按照‘分时复用’的方式,把计算能力分配给多个进程
处理器在进程间频繁切换,因此,即使处理器同一时间只能处理一个指令
但通过在进程间的切换,也能造成多个进程齐头并进的效果

从这个角度来说,集群和单机都实现了多个进程的并行运算
只不过,集群上的多进程分布在不同的主机,而单机的多进程存在于同一主机
并借着‘分时复用’来实现并行

下面是多进程编程的例子:

import multiprocessing

def proc1():
    return 999999**9999
def proc2():
    return 888888**8888
p1 = multiprocessing.Process(target=proc1)
p2 = multiprocessing.Process(target=proc2)

p1.start()
p2.start()

p1.join()
p2.join()

上面程序用了两个进程,进程的工作包含在函数中,分别是函数proc1()和函数proc2()
方法start()用于启动进程,而join()方法用于在主程序中等待相应进程完成

最后,我们要区分一下多进程和多线程,一个程序运行后
就成为一个进程,进程有自己的内存空间,用来存储自身的运行状态,数据和相关代码
一个进程一般不会直接读取其他进程的内存空间
进程运行过程中,可以完成程序描述的工作
但一个进程内部,又可以有多个称为‘线程’的任务
处理器可以在多个线程之间切换,从而形成并行的多线程处理
线程看起来和进程类似,但线程之间可以共享同一个进程的内存空间

相关文章

  • 【第十五天】函数式与并行运算

    第七章 函数式编程 7.1 1.Python中的函数式 函数式编程强调了函数的纯粹性(purity)一个纯函数是没...

  • 《C++Primer》第十四章 重载运算与类型转换

    第十四章 重载运算与类型转换 基本概念 当一个重载符是成员函数时,this绑定到左侧运算对象,成员运算符的(显式)...

  • 了解聚合操作

    聚合操作是Java8的新特性,配合Lambda表达式和方法引用,支持以函数式风格操作集合对象或者并行运算。 为了更...

  • Scala面试题

    scala语言的特点: 集成了面向对象和函数式编程 函数式编程是将计算机的运算视为函数运算 链式编程 Scala中...

  • 七周七并发模型-读书笔记-线程与锁

    目录 概述 线程与锁 函数式编程 Clojure之道-分离标识与状态 Actor 通信顺序进程 数据并行 Lamb...

  • python 10天快速教程 Day4

    本节重点 递归函数 匿名函数 python内置函数 切片 列表生成式 内存地址 可变类型与不可变类型详解 公共运算...

  • MySQL运算符和函数

    分类: ⑴ 字符函数 ⑵ 数值运算符与函数 ⑶ 比较运算符与函数 ⑷ 日期时间函数 ⑸ 信息函数 ⑹ 聚合函数 ⑺...

  • 函数式编程小思考2 笔记

    函数式编程与面向对象编程的比较 什么是函数式编程?是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程...

  • JavaScript语言精髓与编程实践笔记(6)

    函数式语言: 通过连续表达式运算求值的语言 函数是运算元 函数内保存数据 函数内的运算对函数外无副作用 JS 中函...

  • 运算符和函数

    一、字符函数: 二、数值运算符与函数: 三、比较运算符与函数: 四、日期时间函数: 五、信息函数: 六、聚合函数:...

网友评论

    本文标题:【第十五天】函数式与并行运算

    本文链接:https://www.haomeiwen.com/subject/xrajcftx.html