栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Python,使用多进程比不使用它慢

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python,使用多进程比不使用它慢

预计到达时间:现在您已经发布了代码,我可以告诉您有一种简单的方法可以更快地完成您正在做的事情(快100倍以上)。

我看到您正在执行的操作是在字符串列表中的每个项目的括号中添加一个频率。不必每次都计算所有元素(您可以使用cProfile确认这是迄今为止代码中最大的瓶颈),您只需创建一个字典即可将每个元素映射到其频率。这样,您只需要遍历该列表两次-
一次创建频率字典,一次使用它添加频率。

在这里,我将展示我的新方法,对其进行计时,并使用生成的测试用例将其与旧方法进行比较。测试用例甚至表明新结果与旧结果 完全相同注意:
下面您真正需要注意的就是new_method。

import randomimport timeimport collectionsimport cProfileLIST_LEN = 14000def timefunc(f):    t = time.time()    f()    return time.time() - tdef random_string(length=3):    """Return a random string of given length"""    return "".join([chr(random.randint(65, 90)) for i in range(length)])class Profiler:    def __init__(self):        self.original = [[random_string() for i in range(LIST_LEN)]      for j in range(4)]    def old_method(self):        self.ListVar = self.original[:]        for b in range(len(self.ListVar)): self.list1 = [] self.temp = [] for n in range(len(self.ListVar[b])):     if not self.ListVar[b][n] in self.temp:         self.list1.insert(n, self.ListVar[b][n] + '(' +    str(self.ListVar[b].count(self.ListVar[b][n])) + ')')         self.temp.insert(0, self.ListVar[b][n]) self.ListVar[b] = list(self.list1)        return self.ListVar    def new_method(self):        self.ListVar = self.original[:]        for i, inner_lst in enumerate(self.ListVar): freq_dict = collections.defaultdict(int) # create frequency dictionary for e in inner_lst:     freq_dict[e] += 1 temp = set() ret = [] for e in inner_lst:     if e not in temp:         ret.append(e + '(' + str(freq_dict[e]) + ')')         temp.add(e) self.ListVar[i] = ret        return self.ListVar    def time_and_confirm(self):        """        Time the old and new methods, and confirm they return the same value        """        time_a = time.time()        l1 = self.old_method()        time_b = time.time()        l2 = self.new_method()        time_c = time.time()        # confirm that the two are the same        assert l1 == l2, "The old and new methods don't return the same value"        return time_b - time_a, time_c - time_bp = Profiler()print p.time_and_confirm()

当我运行此命令时,它得到的时间为(15.963812112808228,0.05961179733276367),这意味着它快了250倍,尽管这一优势取决于列表的时长和每个列表中的频率分布。我相信您会同意,凭借这种速度优势,您可能不需要使用多处理功能:)

(我的原始答案留在后头,以供后代参考)

ETA:顺便说一句,值得注意的是,该算法在列表长度上大致是线性的,而您使用的代码是二次的。这意味着,元素数量越多,它的优势就越明显。例如,如果将每个列表的长度增加到1000000,则只需要5秒钟即可运行。根据推断,旧代码将花费一天的时间:)


这取决于您正在执行的操作。例如:

import timeNUM_RANGE = 100000000from multiprocessing  import Processdef timefunc(f):    t = time.time()    f()    return time.time() - tdef multi():    class MultiProcess(Process):        def __init__(self): Process.__init__(self)        def run(self): # Alter string + test processing speed for i in xrange(NUM_RANGE):     a = 20 * 20    thread1 = MultiProcess()    thread2 = MultiProcess()    thread1.start()    thread2.start()    thread1.join()    thread2.join()def single():    for i in xrange(NUM_RANGE):        a = 20 * 20    for i in xrange(NUM_RANGE):        a = 20 * 20print timefunc(multi) / timefunc(single)

在我的机器上,多进程操作仅占单线程操作时间的60%。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/451833.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号