具体实施方式
为使本发明实施例的目的、技术方案和优点更加清楚,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本发明实施例的组件可以以各种不同的配置来布置和设计。
因此,以下对在附图中提供的本发明的实施例的详细描述并非旨在限制要求保护的本发明的范围,而是仅仅表示本发明的选定实施例。基于本发明中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
应注意到:相似的标号和字母在下面的附图中表示类似项,因此,一旦某一项在一个附图中被定义,则在随后的附图中不需要对其进行进一步定义和解释。
如图1所示,图1示出了一种应用于本发明实施例中的多段索引并行检索与算分的检索设备100的结构框图。所述多段索引并行检索与算分的检索设备100包括:存储器120、存储控制器130和处理器140。
所述存储器120、存储控制器130、处理器140各元件相互之间直接或间接地电性连接,以实现数据的传输或交互。例如,这些元件相互之间可通过一条或多条通讯总线或信号线实现电性连接。所述多段索引并行检索与算分的检索装置110包括至少一个可以软件或固件(firmware)的形式存储于所述存储器120中或固化在所述多段索引并行检索与算分的检索设备100的操作系统(operating system,OS)中的软件功能模块。所述处理器140用于执行存储器120中存储的可执行模块,例如所述多段索引并行检索与算分的检索装置110包括的软件功能模块或计算机程序。
其中,存储器120可以是,但不限于,随机存取存储器(Random Access Memory,RAM),只读存储器(Read Only Memory,ROM),可编程只读存储器(Programmable Read-Only Memory,PROM),可擦除只读存储器(Erasable Programmable Read-Only Memory,EPROM),电可擦除只读存储器(Electric Erasable Programmable Read-Only Memory,EEPROM)等。其中,存储器120用于存储程序,所述处理器140在接收到执行指令后,执行所述程序,前述本发明实施例任一实施例揭示的流程定义的多段索引并行检索与算分的检索设备100所执行的方法可以应用于处理器140中,或者由处理器140实现。
处理器140可能是一种集成电路芯片,具有信号的处理能力。上述的处理器可以是通用处理器,包括中央处理器(Central Processing Unit,CPU)、网络处理器(NetworkProcessor,NP)等;还可以是数字信号处理器(DSP)、专用集成电路(ASIC)、现成可编程门阵列(FPGA)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件。可以实现或者执行本发明实施例中的公开的各方法、步骤及逻辑框图。通用处理器可以是微处理器或者该处理器140也可以是任何常规的处理器等。
本发明实施例提供了一种多段索引并行检索与算分的检索方法,如图2所示。该方法应用于多个索引段的检索与算分,所述多个索引段属于同一个单片索引,每个所述索引段对应一个独立的检索模块。由于传统的串行检索与算分机制的流程大致为:在索引段内,先执行检索,采用布尔查询召回文档;并将检索到的文档压入队列,以便算分线程读取该队列,取出文档并算分。在索引量增加后,若采用传统的串行检索与算分机制,则必然后导致检索延迟大幅提升,从而影响用户的最终体验。在检索时,为了提高检索效率,于本实施例中,优选地,将单片索引按照哈希算法分成多个索引段进行检索。每个索引段对应一个独立的检索模块,每个检索模块均对应一个检索线程,各个检索线程独立进行检索,相互之间不存在数据共享,避免了因线程之间的同步带来的性能损耗,大幅降低了检索延迟。
其中,图2示出了本发明实施例提供的一种多段索引并行检索与算分的检索方法的流程图,具体包括:步骤S101-S102。
步骤S101:算分模块获取每个所述检索模块检索到的文档信息。
每个检索模块在检索文档信息时,采用布尔查询召回文档,等待算分模块获取每个所述检索模块检索到的文档信息。
为了进一步提高检索效率,降低检索模块间同步带来的性能损耗。本实施例采用无锁队列设计来减小检索延迟,即,每个索引段均启动一个检索模块和分配一个固定大小的缓存空间。其中,每个检索模块对应一个检索线程,检索线程用于检索文档,并将检索到的文档压入与之对应的缓存空间。
这样各个索引段内,检索线程都有一个自己的缓存空间,从而避免检索线程之间共享信息,降低了检索线程间同步带来的性能损耗,大幅降低了检索延迟。每个检索模块将检索到的文档信息存储于对应的缓存空间,以便算分模块获取每个所述缓存空间所存储的文档信息。
其中,在各个索引段内分配的缓存空间的大小可以相同,也可以不同,也可以部分相同。于本实施例中,优选地,在各个索引段内分配的缓存空间均为环形缓存空间。
其中,在所述缓存空间存在未读取的文档信息的情况下,算分模块获取每个所述缓存空间所存储的文档信息的步骤,如图3所示,具体包括:步骤S201-S203。
步骤S201:算分模块获得读取标记位置。
在所述缓存空间存在未读取的文档信息的情况下,算分模块获得读取标记位置。优选地,可以通过查找读取标记位的当前位置来获得该未读取的文档信息在所述缓存空间的实际位置。
其中,读取标记位可以是一个数组指针,用于标记当前可读文档的读取位置。
步骤S202:所述算分模块读取所述读取标记位置处的文档信息。
算分模块根据获取到的读取标记位置来读取位于缓存空间中的文档信息。
步骤S203:读取完毕后,根据所读文档信息的长度更新所述读取标记位置,并将所更新的读取标记位置告知所述缓存空间对应的检索模块,以使该检索模块用于将所检索的文档存储于该读取标记位置处。
当前文档读取完毕后,根据所读文档信息的长度更新所述读取标记位置,以便下次读取,并将根据所读文档信息的长度更新的所述读取标记位置告知与之对应的检索模块,以使该检索模块用于将所检索的文档存储于该读取标记位置处。即将根据所读文档信息的长度更新后的读取标记位置告知与该缓存空间相对应的检索模块,该位置可以被再次利用。在读取的过程中,先读取,后移动指针,可以避免检索模块写入的时候,将算分模块未读取完闭的数据覆盖掉。
其中,可以根据当前读取的实际位置以及读取该文档时的起始位置来判断当前文档是否读取完毕,进一步地,即通过读取该文档时的起始位置到当前读取的实际位置之间的长度L1与当前文档的长度L0相比较,若L1等于L0则表示当前文档读取完毕,若L1小于L0则表示当前文档没有读取完毕。
以图4所示的图例对上述读取过程进行描述:通过读取标记位r1的当前位置来获得该未读取的文档信息在所述缓存空间的实际位置,然后读取所述读取标记位置r1处的文档信息,读取完毕后,根据所读文档信息的长度更新所述读取标记位置,即,将读取标记位置r1更新为读取标记位置r2,并将所更新的读取标记位置r2告知所述缓存空间对应的检索模块。
其中,算分模块获取检索模块检索到的文档信息时,优选地,每次处理完一个检索线程中的所有文档信息后,遍历下一个检索线程的缓存空间,一直循环直到所述检索线程都已结束为止。
为了清楚的说明整个读取过程,如图5所示,其中,图5示出了算分模块读取每个检索模块的缓存空间的读取流程示意图。作为一种优选的实施方式,于本实施例中,优选地,整个缓存空间的大小为size,为了提升检索的性能,进一步优选地,size为2的幂次方大小,例如256、512、1024等,以便于取余操作。用变量w记录当前写入位置,变量r记录当前读取位置,变量buf为数组指针。由于只有一个算分线程读取,所以不会存在其它线程修改读取标记位r的值,因此属于线程安全的操作。整个读取过程大致为:首先判断r的值是否小于w的值,若r的值小于w的值,则表示有未读取的文档;若r的值大于或者等于w的值,则表示没有未读取的文档,则执行pthread_yield,即等待检索模块写入。如果有未读取的文档,则执行i=(r+1)&(size-1)来获得该未读取的文档信息在所述缓存空间的实际位置,然后根据位置读取位于缓存空间中的文档信息,即执行value=buf[i],也就是读取buf[i]中的值来获得位于缓存空间中的文档信息,读取完毕后,根据所读文档信息的长度更新所述读取标记位置,即,执行r++,也就是r=r+1,以便下次读取,并将根据所读文档信息的长度更新的所述读取标记位置r++告知与之对应的检索模块,以使该检索模块用于将所检索的文档存储于该读取标记位置处。
通过r和w之间的差值,可以判定有多少空间是可以写入的,也可以判定有多少空间是可读取的。获取到可读取的范围之后,可以一次性读取所有未读取的文档,减少多次调用的损耗,以提高读取效率。
步骤S102:所述算分模块根据预设的算分规则获得每个所述文档信息对应的算分结果。
算分模块根据预设的算分规则对获得的每个所述文档信息进行算分,以获得每个所述文档信息对应的算分结果。其中,预设的算分规则,可以是目前搜索引擎中常使用的算分规则,例如,可以是根据文档信息中词项权重的计算理论,并由此导出的向量空间模型和基本余弦相似度评分算法来获得每个所述文档信息对应的算分结果。
其中,算分模块作为一个独立的线程,与检索线程并发执行,能有效缩短延迟,算分之后,由于需要做堆排序,所以优选地,整个检索线程共用一个算分线程。由于只有一个算分线程读取,所以不会存在其它线程修改读取标记位的位置,且每次读取文档时,读取标记位的值只增不减,为原子增操作,因此属于安全的操作。
作为一种优选的实施方式,如图6所示,在步骤S102之后,该方法还包括:步骤S103-S106。
步骤S103:判断所有的所述检索模块的检索线程是否结束。
算分模块判断所有的所述检索模块的检索线程是否结束,若所有的所述检索模块的检索线程都已结束,则意味着检索结束,算分也结束。若所有的所述检索模块中至少有一个检索线程没有结束,则意味着检索没有结束,则检索模块可以执行后续的操作,如执行步骤S104。优选地,检索模块可以通过结束标记位来判断检索各个检索线程是否结束。
其中,结束标记位是预先设定用于表示当前检索模块的检索线程结束的标志。
步骤S104:判断当前缓存空间是否有数据可以读取。
若所有的所述检索模块中至少有一个检索线程没有结束,则意味着检索没有结束,则算分模块判断当前缓存空间是否有数据可以读取。若当前缓存空间有数据可以读取,则执行步骤S105。若当前缓存空间没有数据可以读取,则执行步骤S106。优选地,可以通过查找读取标记位的当前位置来判断当前缓存空间是否有数据可以读取。
其中,读取标记位可以是一个数组指针,用于标记当前可读文档的读取位置。
步骤S105:算分模块获取当前缓存空间中的文档,并根据预设的算分规则获得每个所述文档信息对应的算分结果,直到当前缓存空间没有数据可以读取,则遍历下一个检索模块的缓存空间。
若当前缓存空间有数据可以读取,算分模块批量或者逐一读取当前缓存空间中的文档,并根据预设的算分规则获得每个所述文档信息对应的算分结果,直到当前缓存空间没有数据可以读取,则遍历下一个检索模块的缓存空间。
其中,算分模块在取一个检索线程检索到的缓存文档信息时,可以是一次取一个文档,然后对该文档进行算分,之后继续看当前缓存空间是否有数据可读取,直到取完为止才遍历下一个检索模块的缓存空间,也可以是一次性取完当前检索模块的缓存空间中存储的文档信息,然后分别对每一个文档信息进行算分,之后继续判断当前缓存空间是否有数据可读取直到取完为止才遍历下一个检索模块的缓存空间。在取一个检索线程的缓存文档时,若一次性取完所有文档,效率可以进一步。
其中,算分模块获取当前缓存空间中的文档的详细介绍,请参阅步骤S101,以及算分模块根据预设的算分规则获得每个所述文档信息对应的算分结果的详细介绍,请参阅步骤S102,为了避免累赘,此处不再一一描述。
步骤S106:遍历下一个检索模块的缓存空间。
若当前缓存空间没有数据可以读取,则遍历下一个检索模块的缓存空间,在遍历下一个检索模块的缓存空间时,又重复步骤S103-S105。直到所有的检索模块的缓存空间都没有数据可以读取,则意味着检索结束,算分线程也结束。
其中,作为一种优选的实施方式,每个所述检索模块检索时的流程图,如图7所示。其中,图7示出了每个所述检索模块检索时的流程图,具体包括步骤S301-S304。
步骤S301:每个所述检索模块对检索到的文档信息进行合法性判断。
每个所述检索模块均对应一个检索线程,每个所述检索线程在执行检索时,采用布尔查询召回文档,对检索到的文档进行合法性判断,若检索到的文档判断合法,则将判断合法的文档压入与之对应的缓存空间,以便算分线程逐个读取各个所述索引段的缓存空间,取出文档并算分。若检索到的文档判断不合法,则结束该索引段的检索线程。
其中,优选地,对文档的合法性进行判断是指判断该文档是否为空,若该文档不为空,则压入队列。
步骤S302:检索模块判断该检索模块对应的缓存空间是否有写入空间。
若检索到的文档信息判定为合法,则检索模块判断该检索模块对应的缓存空间是否有写入空间,若有写入空间,则执行步骤S303,若没有写入空间,或写入空间不足,则执行步骤S304。
其中,可以根据当前写入的起始位置和该缓存空间的结束位置,来判断当前文档是否可以全部写入当前缓存空间的剩余空间,进一步地,即通过当前写入的起始位置和该缓存空间的结束位置之间的长度L2与当前文档的长度L0相比较,若L2大于或等于L0则表示当前文档可以全部写入当前缓存空间的剩余空间,若L2小于L0则表示当前文档不能全部写入当前缓存空间的剩余空间,也就是说,写入空间不足。
步骤S303:该检索模块将判定为合法的文档信息写入该检索模块对应的缓存空间。
若检索到的文档判断合法后,需要判断该缓存空间是否有写入空间,避免未读取完毕却被写入覆盖。若有写入空间,则将判断合法的文档写入该缓存空间,以便算分模块逐个读取各个所述索引段的缓存空间,取出文档并算分。
优选地,如图8所示,所述的若有写入空间,则该检索模块将判定为合法的文档信息写入该检索模块对应的缓存空间的步骤包括:步骤S401-S403。
步骤S401:检索模块获得该写入空间在所述缓存空间的实际位置。
若有写入空间,则计算出该写入空间在所述缓存空间的实际位置。优选地,可以通过查找写入标记位的当前位置来判断该写入空间在所述缓存空间的实际位置。
其中,写入标记位可以是一个数组指针,用于标记当前文档的写入位置。
S402:该检索模块将判定为合法的文档写入该检索模块对应的缓存空间的相应位置区间,所述相应位置区间的起始位置为所述实际位置,所述相应位置区间的长度与该判定为合法的文档的长度匹配。
根据计算出该写入空间在所述缓存空间的实际位置,将判断合法的文档信息写入该检索模块对应的缓存空间的相应位置区间,即写入的起始位置为该相应位置区间的起始位置,也就是所述实际位置;写入的结束位置为该相应位置区间的长度,也就是该判定为合法的文档信息的长度。
S403:当该判定为合法的文档写入完成后,将所述实际位置更新为所述相应位置区间的结束位置,并将更新后的实际位置告知所述算分模块。
当前判定为合法的文档写入完成后,将所述实际位置更新为所述相应位置区间的结束位置,以便于下次写入,并将更新后的实际位置告知所述算分模块。在写入的过程中,先写入,后移动指针,可以避免算分模块读取的时候,读取到未完全写入的数据。
其中,每个检索模块均对应一个独立的检索线程,与算分模块的算分线程并发执行,能有效缩短延迟。由于每个检索线程均独立完成,相互之间没有数据共享,所以在一个检索线程中不存在其它线程修改写入标记位的位置,且每次写入文档时,写入标记位的值只增不减,为原子增操作,因此属于安全的操作。
以图9所示的图例对上述写入过程进行描述:通过获得写入标记位w1的当前位置来确定该文档信息写入的实际位置,然后将判定为合法的文档写入该检索模块对应的缓存空间的相应位置区间,写入完毕后,根据所写入的文档信息的长度更新所述写入标记位置w1,即,将写入标记位置w1更新为写入标记位置w2,并将所更新的写入标记位置w2告知算分模块。其中,相应位置区间的起始位置为w1,结束位置为该相应位置区间的长度,也就是该判定为合法的文档信息的长度,即结束位置为w2。
为了清楚的说明整个写入过程,如图10所示,其中,图10示出了每个检索模块将判定为合法文档信息写入对应的缓存空间的写入流程示意图。于本实施例中,优选地,整个缓存空间的大小为size,为了提升检索的性能,进一步优选地,size为2的幂次方大小,例如256、512、1024等,以便于取余操作。用变量w记录当前写入位置,变量r记录当前读取位置,变量buf为数组指针。当有值写入时,只会改变变量w的值,并且只增不减,为单线程修改。由于对变量w的修改为原子增操作,因此属于线程安全的操作。整个写入过程大致为:首先判断w-size的值是否小于r的值,若w-size的值小于r的值,则表示有写入空间,若w-size的值大于或等于r的值,则表示没有写入空间,则执行pthread_yield,即等待算分模块读取。如果有写入空间,则执行i=(w+1)&(size-1)来获得该写入空间在缓存空间的实际位置;然后将判定合法的文档信息写入到缓存空间的相应位置,即执行buf[i]=value,也就是将文档的值value写入到buf的相应位置;最后根据写入的文档长度value更新写入的标记位置w,即,w=w+1,以便下次写入,并将更新后的实际位置w++告知算分模块。
通过r和w之间的差值,可以判定有多少空间是可以写入的,也可以判定有多少空间是可读取的。获取到可写入的范围之后,可以批量写入多个判定为合法的文档,以提升写入效率。
步骤S304:检索模块等待算分模块读取该索引段的缓存空间,取出文档并算分,直到有写入空间为止。
若没有写入空间,或写入空间不足,则检索模块等待算分模块读取该索引段的缓存空间,取出文档并算分,直到有写入空间为止。
其中,算分模块读取该索引段的缓存空间,取出文档并算分的详细介绍,请参阅对步骤S101和S102的介绍,为了避免累赘,此处不再描述。
其中,每个检索模块均对应一个独立的检索线程,与算分模块的算分线程并发执行,能有效缩短延迟。如图11所示,其中,图11示出了多个检索模块并行检索及与算分模块并发执行的示意图。多个检索模块并行检索,各个检索模块之间相互独立,每个检索模块独立进行检索,即doc=seek(),并将查找到的文档写入与之对应的缓存空间,即push(doc)。算分模块与检索模块并发执行,以有效缩短延迟,算分模块读取缓存空间中的文档并算分,即,rank(doc)。
本发明实施例还提供了一种多段索引并行检索与算分的检索装置110,如图12所示。该多段索引并行检索与算分的检索装置110包括:检索模块111和算分模块121。
所述检索模块111,用于检索文档信息,并获取检索到的文档信息。
其中,如图13所示,检索模块111包括:第一获取单元112、第一判断单元113、写入单元114和第一更新单元115。
所述第一获取单元112,用于获取检索到的文档信息,以及还用于获得该写入空间在所述缓存空间的实际位置。
所述第一判断单元113,用于对检索到的文档信息进行合法性判断,以及还用于判断该检索模块对应的缓存空间是否有写入空间。
所述写入单元114,用于将判定为合法的文档写入该检索模块对应的缓存空间的相应位置区间,所述相应位置区间的起始位置为所述实际位置,所述相应位置区间的长度与该判定为合法的文档的长度匹配。
所述第一更新单元115,用于当该判定为合法的文档写入完成后,将所述实际位置更新为所述相应位置区间的结束位置,并将更新后的实际位置告知所述算分模块。
所述算分模块121,用于获取每个所述检索模块检索到的文档信息;以及,所述算分模块121,还用于根据预设的算分规则获得每个所述文档信息对应的算分结果。
其中,如图14所示,所述算分模块121包括:第二获取单元122、读取单元123、第二更新单元124和第二判断单元125。
所述第二获取单元121,用于获取每个所述检索模块检索到的文档信息,以及还用于根据预设的算分规则获得每个所述文档信息对应的算分结果;此外,该第二获取单元121还用于获得读取标记位置。
所述读取单元123,用于读取所述读取标记位置处的文档信息。
所述第二更新单元124,用于根据所读文档信息的长度更新所述读取标记位置,并将所更新的读取标记位置告知所述缓存空间对应的检索模块,以使该检索模块用于将所检索的文档存储于该读取标记位置处。
所述第二判断单元125,用于判断所有的所述检索模块的检索线程是否结束;以及还用于判断当前缓存空间是否有数据可以读取。
以上各模块可以是由软件代码实现,此时,上述的各模块可存储于电子设备的存储器内。以上各模块同样可以由硬件例如集成电路芯片实现。
需要说明的是,本说明书中的各个实施例均采用递进的方式描述,每个实施例重点说明的都是与其他实施例的不同之处,各个实施例之间相同相似的部分互相参见即可。
本发明实施例所提供的多段索引并行检索与算分的检索装置110,其实现原理及产生的技术效果和前述方法实施例相同,为简要描述,装置实施例部分未提及之处,可参考前述方法实施例中相应内容。
在本申请所提供的几个实施例中,应该理解到,所揭露的装置和方法,也可以通过其它的方式实现。以上所描述的装置实施例仅仅是示意性的,例如,附图中的流程图和框图显示了根据本发明的多个实施例的装置、方法和计算机程序产品的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段或代码的一部分,所述模块、程序段或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现方式中,方框中所标注的功能也可以以不同于附图中所标注的顺序发生。例如,两个连续的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或动作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。
另外,在本发明各个实施例中的各功能模块可以集成在一起形成一个独立的部分,也可以是各个模块单独存在,也可以两个或两个以上模块集成形成一个独立的部分。
所述功能如果以软件功能模块的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、只读存储器(ROM,Read-Only Memory)、随机存取存储器(RAM,Random Access Memory)、磁碟或者光盘等各种可以存储程序代码的介质。需要说明的是,在本文中,诸如第一和第二等之类的关系术语仅仅用来将一个实体或者操作与另一个实体或操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。而且,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、物品或者设备中还存在另外的相同要素。
以上所述仅为本发明的优选实施例而已,并不用于限制本发明,对于本领域的技术人员来说,本发明可以有各种更改和变化。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。应注意到:相似的标号和字母在下面的附图中表示类似项,因此,一旦某一项在一个附图中被定义,则在随后的附图中不需要对其进行进一步定义和解释。