python多进程逐对比较文档相似度+均分比较次数

多进程提高运算效率

最近用python做数据处理,363个文件逐对比较相似度,总共65703次。之前学习神经网络发现cpu使用率只有30%多,应该是只用了一核,这次计算密集型任务,用多进程跑下看看提速效果。先把分析对象拆成多份,让每份的数量基本均匀,然后多线程跑,风扇果然嗡嗡起来了。下面是一个小样本量的测试结果,由于每次比对的计算量不同,所以效率不会是线性提升,我做了一个计算量相同的测试,效率也不是线性提升的,不是简单的多用一核就能提高一倍效率,这个好理解。总cpu使用率相对每个cpu使用率是线性累加的。我的cpu是i7-7500U CPU @ 2.70GHz~2.90G,双核双线程四个逻辑核。三个线程基本就跑满了。对于大数据量的场景,多线程的威力就发挥得更明显了。

我有一次跑的过程中报错了,没细看,里面有pandas的内容,直觉是多进程可能不稳定,后面再跑没遇到过。

运行环境 进程数 总cpu使用率 每进程cpu使用率 耗时(s)
ubuntu子系统 1 37% 32 94
ubuntu子系统 2 65% 31 67
ubuntu子系统 3 96% 30 60
ubuntu子系统 4 100% 24 57

细致比较多进程

364个文件逐对比较,总共比较次数为66066

进程 起始时间戳 处理条数 耗时(s)
1个进程 - - -
进程1 1528290177.8083532 66066 19.36804223060608
66066 19.423198461532593
2个进程 - - -
进程1 1528290066.5728095 33153 10.518495559692383
进程2 1528290066.5882878 32913 10.646009922027588
66066 10.698017120361328
3个进程 - - -
进程1 1528289094.8444376 22011 9.382812976837158
进程2 1528289094.8605711 22110 9.47968602180481
进程3 1528289094.8762245 21945 9.627197742462158
66066 9.712886095046997
4个进程 - - -
进程1 1528289148.3423731 16302 9.519663095474243
进程2 1528289148.3572035 16611 9.670548915863037
进程3 1528289148.376095 16471 9.6192147731781
进程4 1528289148.3954604 16682 9.710239171981812
66066 9.799142360687256

结论:1个进程到2个进程接近线性提升,3个进程提升微弱,4个进程反而比3个进程更慢。

多进程代码

if __name__ == '__main__':

    start = time.time()

    # 进程安全的列表
    result = Manager().list()

    # 下面均分函数的输出
    shred = [(0, 49), (49, 106), (106, 182), (182, 364)]

    # 将进程添加进列表
    task = []

    for i in shred:
        task.append(Process(target=compare, args=(i[0], i[1], result)))

    # 逐个启动进程,不要把join直接写在start后面,那样就成单进程了
    for i in task:
        i.start()

    # 进程全部阻塞以后再打印列表    
    for i in task:
        i.join()

    for i in result:
        print(i)

    print(time.time() - start)

均分比较次数

n个文件逐对比较总共比较len(list(itertools.combinations(range(100),2)))次,写了一个均分比较次数的函数,比较弱,但还好使。我觉得这可以作为一道面试题。

"""
"""
均分比较次数
输入:file-文件数量 shred-份数
输出:列表,元素是分段起止位置组成的元祖
"""
def find_div_pos(file, shred):
    s = sum(range(file))
    point = [s * i / shred for i in range(1, shred + 1)][:-1]
    result = []
    for p in point:
        accu = file - 1
        # 倒着迭代是为了更快找到切分点
        # 每次都从头开始迭代影响效率,但是可以忽略
        for i in range(file - 2, 0, -1):
            accu += i
            if abs(accu - i - p) > abs(accu - p) < abs(accu + i - 1 - p):
                result.append(file - i)
                break
    return list(zip([0] + result, result + [file]))


re = find_div_pos(364, 4)

猜你喜欢

转载自blog.csdn.net/qq_35753140/article/details/80601415