语言:python3.6
环境:pycharm
**第一题:
设计一个test.cpp,定义变量:unsigned int sum=0;创建2个线程T1和T2, T1的行为:sum+=1;T2的行为: sum+=2;当sum大于1000000时,输出sum的值,程序结束。**
Q1:该程序运行10次,记录运行结果。
Q2:10次运行结果是否一致?若不一致,请解释原因。
运行结果不一致,原因是两条线程运行时间不完全一致,而是交叉运行。这就是多线程共享全局变量出现的问题。因为CPU是采用时间片轮询的方式进行几个线程的执行。假设CPU先轮询到addOne(),sum此时为100000。然后执行addOne,执行完sum+=1后,sum更新为1000001,此时addTwo开始执行,addTwo取得的sum为刚才addOne操作之后的sum,也就是1000001,执行sum+=2之后,sum值为100003。
Q4:是否可以消除test.exe多次运行时其结果的不一致性?请给出解决方案,测试其可行性。
通过加锁可以解决多次运行结果不一致的问题。加锁也是多线程中的常规操作。当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
lock = threading.Lock() # 取得锁
lock.acquire() # 上锁
lock.release() # 解锁
初始代码:
import threading
sum = 0
def addOne():
global sum
while sum <= 1000000:
sum = sum + 1
print('th1sum',sum)
def addTwo():
global sum
while sum <= 1000000:
sum = sum + 2
print('th2sum',sum)
if __name__ == '__main__':
thraed1 = threading.Thread(target=addOne) # th1
thraed2 = threading.Thread(target=addTwo) # th2
thraed1.start()
thraed2.start()
thraed1.join()
thraed2.join()
加锁后代码:
import threading
sum = 0
lock = threading.Lock()
def addOne():
global sum
lock.acquire()
while sum <= 1000000:
sum = sum + 1
lock.release()
print('th1sum',sum)
def addTwo():
global sum
lock.acquire()
while sum <= 1000000:
sum = sum + 2
lock.release()
print('th2sum',sum)
if __name__ == '__main__':
thraed1 = threading.Thread(target=addOne) # th1
thraed2 = threading.Thread(target=addTwo) # th2
thraed1.start()
thraed2.start()
thraed1.join()
thraed2.join()
第二题
设计一个quadratic.cpp,用于求解N个(n=10000或100000…)一元二次方程,方程的系数a、b、c为随机整数,其中a ≠ 0。将quadratic.cpp改造为采用2个线程协同求解一元二次方程的Multithreading2.cpp。
Q1:分别计算quadratic.cpp与Multithreading2.cpp的运行时间。
N100000
quadratic.py的运行时间为2.14
Multithreading2.py的运行时间为1.86
Q2:计算Multithreading2.cpp的加速比。
加速比=1.14
Q3:分析总结串行算法并行化改造的难点。
1、如何将计算任务拆分成多个部分并分解到多个核心上同时运行是一个难点。
2、不是所有的串行算法都可以直接并行化的,串行算法并行化改造对程序有一定的要求。
3、双核CPU 的运算力难以保证充分利用:并行计算能够将一个常规的串行程序分解成两个部分,使之能够在CPU 的两个核心上并行运算,并且希望能够尽量发挥双核心的计算能力。一般来说,如果两个核心的运算量基本相当,那么总的运算效率较高。如果出现某个核心空闲等待的状态,双核CPU 的运算力就没有被充分的利用起来。
Q4:检索主流的支持并行计算的技术、架构与平台,简述其特点。
- 1.CUDA™是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。 它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。
开发人员可以使用C语言来为CUDA™架构编写程序,C语言是应用最广泛的一种高级编程语言。所编写出的程序可以在支持CUDA™的处理器上以超高性能运行。 - MapReduce:MapReduce是Google提出的一个软件架构,用于大规模数据集的并行运算。
- Spark:Apache Spark是一种包含流处理能力的下一代批处理框架。与Hadoop的MapReduce引擎基于各种相同原则开发而来的Spark主要侧重于通过完善的内存计算和处理优化机制加快批处理工作负载的运行速度。Spark可作为独立集群部署(需要相应存储层的配合),或可与Hadoop集成并取代MapReduce引擎。
常规方法代码:
import math
import random
import time
def GetCoefficient():
a = random.randint(1,100)
b = random.randint(-100,100)
c = random.randint(-100,100)
return a,b,c
def Calculate():
a, b, c = GetCoefficient()
delta= b*b-4*a*c
if delta< 0:
print("此方程无解")
elif delta== 0:
s = -b/(2*a)
print("方程有唯一解x=",s)
else:
x1 = (-b+(math.sqrt(delta)))/(2*a)
x2 = (-b-(math.sqrt(delta)))/(2*a)
print("x1=", x1, "---------", "x2=", x2)
if __name__=='__main__':
t1 = time.time()
for i in range(0, 100000):
Calculate()
t2 = time.time()
print('time:', t2-t1)
多线程方法代码
import math
import random
import time
def GetCoefficient():
a = random.randint(1,100)
b = random.randint(-100,100)
c = random.randint(-100,100)
return a,b,c
def GetDelta():
a,b,c = GetCoefficient()
delta = b*b - 4*a*c
return a,b,c,delta
def Calcalute():
a,b,c,delta = GetDelta()
if delta<0:
print("此方程无解")
elif delta == 0:
print("此方程有唯一解:x =",(-b/(2*a)))
else:
x1 = ((-b)+(math.sqrt(delta))/(2*a))
x2 = ((-b)-(math.sqrt(delta))/(2*a))
print("x1=",x1,"|","x2=",x2)
# print(delta)
if __name__ == '__main__':
t1 = time.time()
for i in range(100000):
Calcalute()
t2 = time.time()
print("time:",t2-t1)