使用多线程在巨大的树形结构中查找文件的方法

如何解决使用多线程在巨大的树形结构中查找文件的方法

| 我有一棵以所有目录和文件为节点的树。我想搜索一个特定的文件。假设树已广泛传播,我想进行广度优先搜索以找到某些特定文件,并且也使用多线程进行搜索。我应该如何使用多线程?有什么好的方法?     

解决方法

在某些情况下,多线程搜索将提供有用的加速效果-例如,如果树跨越多个磁盘,或者某些磁盘/节点通过某个网络间接访问。 我当然不想尝试为每个文件夹创建线程。那就是成千上万的创建/运行/终止,成千上万的堆栈分配/免费等。总的来说,这是可以避免的开销。 可以进行多线程搜索,但是正如其他发布者所说的那样,请首先查看可用的替代方法。然后阅读这篇文章的其余部分。然后再看 我曾经使用类似于Matt建议的队列方法来做类似的事情。 我不想再做一次: 我使用了一个生产者-消费者工作队列,在该队列上有6个线程等待工作(6个线程是因为测试表明这对于我的问题而言是最佳的)。线程在启动时全部创建一次,并且永不终止。尽管性能不佳,关闭AV,关闭216/217 messageBoxes等,但这种持续的create / load / run / waitFor / getResult / terminateIfYoureLucky东西似乎都没有受到开发人员的欢迎。 这项工作以\'folderSearch \'类的形式出现,其中包含要搜索的路径,要调用的文件匹配函数事件以及执行搜索的FindFirst / FindNext循环方法。我在启动时在一个池中创建了数百个(即,推入另一个P-C池队列:)。当FF / FN迭代文件夹中的文件以查找匹配的文件时,遇到一个子文件夹会导致从池中提取另一个folderSearch实例,并用新路径加载它并将其推入工作队列-某些线程会然后将其拾起并迭代子文件夹。该类有一个匹配文件路径的列表,以及一个\ results \事件(当然,以\'this \'作为参数)可以调用,如果发现有兴趣的话。如果folderSearch到达了树枝的尽头,什么也没找到,也没有什么要搜索的东西,它将把自己释放回池中((好吧,线程会这样做,但您知道我的意思:)。 不需要任何显式的“负载平衡”。如果一个节点异常深,则自然会以所有六个线程在其子树上工作而结束,因为其他路径已耗尽。 完整搜索3个磁盘意味着从池中弹出3个文件夹搜索,并用\'C:\\\',\'E:\\\',\'F:\\\'以及文件匹配方法和然后将它们推入工作队列。然后,磁盘发出嘎嘎声,最终将触发事件并产生结果。在我的情况下(Windows),事件PostMessage将folderSearch对象传递到一个UI线程,该结果将结果存储在treeView中,然后再将folderSearch池化以供重复使用。 即使在我只有一个核心的旧开发箱中,该系统的速度也比在3个磁盘上进行简单顺序搜索的速度快约2.5倍,这是因为所有3个磁盘都是并行搜索的。我怀疑它在现代设备上是否会显示出同样的优势,因为限制因素可能是由磁盘上等待的IO所主导。 出人意料的是,只有一个磁盘,但速度却没有那么快。不知道为什么-由于所有额外的复杂性,按权利要求应该变慢。 自然地,有问题。其中之一是,由于搜索会引发大量结果,因此该池将为空,因为UI无法跟上线程的速度,因此所有folderSearch对象都被卡在PostMessages中,并排入了UI队列,因此降低了搜索线程的速度他们必须在池队列上等待,直到PostMessages得到处理,然后将folderSearch \返回到池中。这也意味着在搜索结束之前,UI一直被有效阻止,并且可以追上来,而一开始就否定了从搜索中脱机的优点之一:(对于较小的结果集,它可以正常工作。 另一个可能的问题是,结果以“非自然”的方式返回,以一种非常混乱的方式交错,以至于诸如组装树状视图之类的事情比单线程递归搜索要复杂得多-您必须四处寻找在适当的位置将结果填充到treeView中。正如我发现的那样,这使GUI负担了很多工作,并且可能抵消大量结果的搜索速度优势 该设计可以同时运行多个搜索。作为测试,我会一次加载几个3个磁盘的搜索(加载树视图时不是这样-我只是将找到的文件数量转储到GUI消息处理程序的备注行中)。这造成了巨大的嘎嘎声,并使一切变得缓慢,但最终确实完成了所有搜索而没有崩溃。我不经常这样做,因为我担心自己的磁盘不佳。不要在家尝试 我从不知道有多少线程挂在队列上。六个是关于我的带有本地磁盘的旧盒子上的最佳选择。如果混合使用网络磁盘,则更多的选择可能更好,因为与本地磁盘读取相比,网络调用往往会阻塞一个线程更长的时间。从未尝试过这样做,但是在更多线程上加载不会影响本地磁盘的性能,只是使用更多内存不会带来任何额外优势。 另一个问题是找出搜索是否实际结束了-所有结果都在..还是某个线程还在等待慢速或实际上无法访问的网络驱动器上?只进行一次搜索,我就能知道是因为搜索结束后池又变满了(我将池级别转储到1s GUI计时器的stausBar上)。在我的应用中没关系,但是在其他应用中,可能... 取消搜索是一个类似的问题。这些事情将需要另一个\'searchClass \'来控制每个搜索。分配给搜索的每个folderSearch都必须保留对searchClass的引用,以便任何处理folderSearch的线程都可以了解是否设置了异常终止,如果这样,则停止对该folderSearch进行处理。我不需要这个,所以没有实现它。 那里的错误报告。如果网络驱动器连接失败,例如,几个(很可能是全部!),线程可能会阻塞很长时间,然后引发异常。然后他们都立刻消失了。捕获消息被加载到folderSearch的\'errorMess \'字段中,并触发结果事件。人类可察觉的证据-嘎嘎作响停止了。一分钟什么都没发生,然后[线程数]错误立即出现。 请注意其他海报和我的经验中的注意事项。如果您确实真的出于某些特殊的搜索目的需要它,请尝试这种操作,并且您对多线程应用程序百分百满意。如果您可以通过单线程搜索,对文件资源管理器的shell调用或几乎其他任何方法摆脱现实,那就可以这样做! 自从使用FTP服务器生成树以来,我一直使用相同的方法。尽管服务器管理员可能对多个连接不满意,但速度也要快得多 Rgds, 马丁     ,在每个分支中对工作分配未知的树搜索任务进行多线程处理并非易事(例如,出现很多约束满足问题)。 最简单的方法是创建一个任务队列(由互斥锁保护)。用根节点的所有子节点填充此队列。生成N个线程(每个可用的CPU内核一个),并让它们搜索每个节点。您可以采取多种技巧来避免某些不良情况(如果任何线程发现其节点“异常深”,则可以让它们将新任务添加到与希望其他线程进行探索的子目录相对应的队列中。)节点深度分布均匀,并且根节点有很多子节点,您可以完全避免排队-只需为每个具有索引i的线程分配探索X%N + i的任务(其中X是根节点的子节点数)。 )     ,        我的第一个回答是说“只是使用nftw,而不必多线程处理”。如果碰巧有一个nftw的实现使树以多线程的方式运行,那么您将免费获得多线程(我不知道任何此类实现)。如果您确实想执行多个线程,我建议您使用nftw并为回调中的每个目录生成一个新线程,但是目前尚不清楚这比跟随Kanopus \更容易(或有任何不同)的建议。在考虑了片刻之后,我回到了我的第一个建议,想知道为什么要使用多个线程来执行此操作。拥有更多线程不太可能加快搜索速度。使用nftw。不用担心线程。     ,        假设树中的每个节点都代表一个目录(及其中的文件),并且还假定您可以打开的线程数没有限制: 输入根节点(如果它具有
n
个子目录),创建
n - 1
个线程以在第一个
n - 1
中进行搜索,然后继续搜索最后一个子目录。根据需要重复。     ,        树结构通常不适合并行化。假设您已将所有节点加载到内存中,请尝试对其进行组织,以使它们占据一个数组-毕竟,它们需要驻留在串行的RAM中-并出于搜索目的而忽略它们的树结构。然后使用某种并行
for
循环迭代数组的元素。流行的选择是OpenMP,或者您可以在Visual Studio中尝试ѭ4。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <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,添加如下 <property name="dynamic.classpath" value="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['font.sans-serif'] = ['SimHei'] # 能正确显示负号 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 -> 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("/hires") 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<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-