并行化第n个阶乘python程序的更好方法?

如何解决并行化第n个阶乘python程序的更好方法?

我有这个python代码来连续计算n个“ 1”的第n个阶乘。我已经能够很好地对其进行优化,包括使用多处理模块将其调整为在所有内核上运行。但是我注意到第7个进程(因为从上到下,这是值的下限)明显快于其余线程。线程0-6平均耗时32秒,n = 11,而线程7仅耗时12秒。我希望数字本身越大,差异就越大,但我不希望有如此明显的差异。

我的代码中是否存在除了导致这堵大墙的计算之外的其他遗漏?我已经验证了输出,并且每个段的长度几乎相同(线程7经过几十次计算而稍长一些,但是从总体上看,这没什么,线程7还是运行最短的)

是否有更好的方法来并行化此方法以提高效率?使线程的增量不相同会有所帮助吗?

编辑:添加python版本信息

Win32上的Python 3.8.5(tags / v3.8.5:580fbb0,2020年7月20日,15:57:54)[MSC v.1924 64位(AMD64)]

(我做了25次n = 11的测试,所有测试都与此类似)

Duration of each Process

import multiprocessing
import argparse
from datetime import datetime
from math import log10

parser = argparse.ArgumentParser(
    formatter_class=argparse.HelpFormatter,description="Calcs n factorial",usage=""
)

parser.add_argument("-n","--number",type=int,default=2)

args = parser.parse_args()

def getlog(send_end,i,threads,num,n,inc):
    begin = datetime.now()
    start = num-inc*i
    end = num-inc*(i+1) if i < threads-1 else 0
    output = sum(map(log10,range(start,end,-n)))
    send_end.send(output)
    final = datetime.now()
    duration = final-begin
    print("{},{},{}".format(i,duration,start,end))

def main():
    n = args.number
    num = int('1'*n)
    threads = multiprocessing.cpu_count() if num/multiprocessing.cpu_count() > multiprocessing.cpu_count() else 1
    inc = int(num/threads)
    inc -= inc%n
    jobs = []
    pipe_list = []
    for i in range(threads):
        recv_end,send_end = multiprocessing.Pipe(False)
        p = multiprocessing.Process(target=getlog,args=(send_end,inc))
        jobs.append(p)
        pipe_list.append(recv_end)
        p.start()
    for proc in jobs:
        proc.join()
    e = sum([output.recv() for output in pipe_list])

    print('%.2fe%d' % (10**(e % 1),e // 1))
    
if __name__ == '__main__':
    start = datetime.now()
    main()
    end = datetime.now()
    print(end-start)

解决方法

@echo off pushd "D:\Jaye\Programming\Web\Project\scss" for /f "delims=" %%i in ('dir /b /s /a-d *.scss ^| findstr /V /IRC:"^_"') do echo Non of these starts with "_": "%%~i" popd 如果需要使用超出C range范围之外的值,请使用较慢的实现-请参见source

您在Windows上,其中C long是32位(即使在64位Python版本上)。进程7是唯一将范围元素放在C long范围内的程序。

,

以不同的幅度迭代一百万个数字的时间:

from timeit import repeat
from collections import deque

for e in range(26,36):
    n = 2**e
    t = min(repeat(lambda: deque(range(n,n+10**6),0),number=1))
    print(e,t)

在64位Windows上的32位Python上为我提供的输出,请注意,从2 30 增至2 31 时的巨大增长:

26 0.020830399999999916
27 0.020713199999999987
28 0.02067260000000004
29 0.021565000000000056
30 0.021966000000000152
31 0.16404839999999998
32 0.16630840000000013
33 0.16394810000000026
34 0.16302989999999973
35 0.1655395999999998

在范围上映射log10仍显示大约相同(绝对)的增加:

26 0.14502039999999994
27 0.1435571
28 0.14378349999999962
29 0.14398270000000002
30 0.14687919999999988
31 0.29700239999999933
32 0.29499730000000035
33 0.2949491999999996
34 0.2964432000000006
35 0.2918921999999995

代码:

from timeit import repeat
from collections import deque
from math import log10

for e in range(26,36):
    n = 2**e
    t = min(repeat(lambda: deque(map(log10,range(n,n+10**6)),t)

您在线程7中的数字都是快幅度,而其他线程中的大多数/所有数字都是慢幅度。

您可以更改范围,以使它们都经过所有幅度。更简单的示例:使用范围range(0,10)range(10,20)代替范围range(0,20,2)range(1,2)

顺便说一句,当从2 30 变为2 31 时,我看到64位Windows上的64位Python也有类似的增长。但是在Linux上的64位Python上,从2 30 到2 31 并没有增加,但从2 62 62>时也有类似的显着增加。 sup>到2 63

更新

以上删除线段落不正确。正如enter image description here所示,并不是“数字”很慢(我曾想过),而是有两个完全独立的range实现。而且只有您的线程7使用快速线程(少量线程)。因此,我上面提出的使所有线程/范围遍历所有幅度的建议实际上会适得其反。它不会使速度较慢的速度更快,而只会使速度较慢的速度和其他速度一样慢。闷闷不乐。

因此,另一种建议是:不要像给每个线程一个范围那样,而是给每个线程一个long范围的一部分和一个非long范围的一部分。那应该使所有线程都同样快,并减少整体时间。但是效果会很小,对于较大的n甚至会更小,我怀疑是否值得这样做。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-