问候,
我需要将存储在文本文件中的两个极长整数值相乘(通过GMP导出(确切地说是MPIR),因此它们可以是任何基础中的任何一个)。现在,我通常只是通过mpz_inp_str()函数导入这些整数并在RAM中执行乘法,但是,这些值太长以至于我无法真正加载它们(每个大约1 GB的数据)。最快的方法是什么?也许有一些外部库已经做过这种事了吗?是否有任何易于实现的方法(性能不是非常重要,因为此操作只执行一次或两次)?
tl; dr:我需要将值大得多,它们不适合进程内存限制(Windows)。
感谢您的时间。
答案 0 :(得分:4)
我不知道是否有支持此功能的库,但您可以在每个真正大数字(RBN)的部分使用GMP / MPIR。也就是说,首先将每个RBN分解为可管理的,统一大小的块(例如,10M数字块,预计大多数有效数字的大小不足,也见下文)。
RBN1 --> A B C D E RBN2 --> F G H I J
分块可以在基数10中完成,所以只需读取< chuck_size>每件文件中的字符。然后一次乘以每个数字的块。
AxF BxF CxF DxF ExF + AxG BxG CxG DxG ExG + AxH BxH CxH DxH ExH + AxI BxI CxI DxI ExI + AxJ BxJ CxJ DxJ ExJ
在内存中执行最后总和的每一列。然后,将进位保持在内存中,将列写入磁盘,重复下一列...对于进位,将每列和结果转换为带有GMP的字符串,写出底部<块大小>结果的一部分,并将顶部读回作为进位的GMP int。
我建议为每次乘法动态选择一个块大小,以便在内存中保留每一列;数字越大,需要完成的列添加越多,块大小就越小。
对于读取和写入,我建议使用内存映射文件,boost有一个很好的this接口(请注意,这不会加载整个文件,它只是基本上缓冲虚拟内存上的IO) 。为每个输入RBN编号打开一个映射文件,并为size = size(RBN1)+ size(RBN2)+ 1打开一个输出;对于内存映射文件,文件访问被视为原始char *,因此您可以使用gmp c-string io方法直接读/写块。您可能需要读入一个中间缓冲区,以便为GMP使用NULL终止字符串(除非您想暂时更改内存映射文件)。
这不是很容易正确实现,但这又不是一个特别容易的问题(可能只是单调乏味)。这种方法的优势在于它完全反映了GMP在内存中的作用,因此这些算法是众所周知的。