9. 高效融合计算¶
融合计算是一种将多种计算技术有机结合的全新信息技术模式。在量子计算场景中,融合计算指的是将量子计算与经典计算(特别是性能强大的超级计算机或云计算机)联合使用,以达到特定目的,例如利用量子计算的并行计算能力来加速经典计算。
对于现有的经典算法和标准软件,目前尚无直接且快速的方法使其能够利用量子计算。相反,需要对其进行重新改写和重新设计,以替换其中可由量子计算提供计算的部分,从而实现量子计算与经典计算的融合。换句话说,需要通过使用量子算法替代经典算法,或者从计算问题的起源出发,使用量子计算的方法重新设计解决问题的方法。
由于当前量子计算机的能力有限,在数据准备阶段或数据最后处理阶段等过程中仍需要经典计算的支持。因此,目前任何一个程序都具有经典与量子混合的形式,只是其经典部分是否需要强大的经典计算能力的支持而已。
另一方面,如果一个问题的解决已经依赖于量子计算,这也意味着原有的借助于经典计算的计算能力无法满足需求。在使用量子计算机的过程中,仍可以继续借助于大型、超级计算机类的经典算力提供支持,这是可以接受的形式。
从程序结构的角度来看,量子计算与经典计算的融合可以分为三种形式。
- 并行执行:经典程序和量子程序并行执行,最终利用两者的结果进行比对和相关处理,得到最终结果。
- 交互循环:经典程序和量子程序之间相互循环,交换计算结果,相互影响,直到满足条件跳出循环,得到最终结果。
- 迭代循环:经典程序和量子程序之间相互循环,交换计算结果,相互影响,将结果迭代到上层经典循环中,如此往复,直到满足条件跳出循环,得到最终结果。
在更深层次的数据互动方面,有以下三种方式:
- 将经典参数传递给量子线路,作为线路中的参数。
- 将经典参数作为判断条件,根据条件执行不同的量子线路。
- 根据经典参数,重新组装量子线路结构。
基于上述分析,结合现有的超级计算机和云计算平台,用户可以通过网络调用这些资源,无需拥有本地的超级计算机或量子计算机,从而实现高性能的融合计算。然而,考虑到通过网络调用超级计算机和量子计算机的数据交互过程可能效率较低,严重影响整体的计算效率。
因此,将超级计算机和量子计算机集成在一起,并调整调用机制,可以实现更高效的融合计算。
针对这一需求,创新院设计了高效融合计算模式,即Runtime模式。该模式允许用户通过网页将融合计算所需的计算文件(Python)、数据和环境配置提交到量子计算机专用网络内的经典计算机上运行。该模式的计算代码与常规网络调用量子计算机的代码相同,但实际运行模式经过重新设计,能够直接调用量子计算机,从而实现更高效的计算任务完成。
Runtime的具体使用方式距离如下,给用户参考。
PS:现阶段Runtime模式处于测试阶段,使用权限需要单独申请,请邮件联系:support@quantumcomputer.ac.cn,说明具体需求,申请权限。
Runtime模式的使用很简单,即
- 准备运行环境包需求文件(可选)
- 准备主运行程序,并将入口程序文件名改为main.py
- 准备其他数据文件(可选)
- 将上述流程中的所有文件压缩为一个zip文件,为简短英文名称,如main.zip
- 通过云平台web页面提交任务,选择资源等。
- 等待结果,并通过web端下载最终结果数据,或报错记录。
9.1 运行环境配置(可选)¶
当前的基础运行环境为python 3.8,并且预装了一些Python包(见附件),以减少用户运行环境时预装环境的时间成本,我们会根据用户对包的需求反馈,不断更新预装库和版本,请留意查看帮助文档的附件。
当预装库不满足用户需求,且官方暂时未做出统一的库更新时,用户可以准备一个文件名为requirements.txt的文件,内容如下,格式与Python包安装时的格式相同。
切记只提供真实需求的包,不要直接导出自己工作环境的包,过多的包可能会导致环境安装时间过长。
APScheduler==3.10.1
attrs==23.1.0
Automat==22.10.0
backports.zoneinfo==0.2.1
certifi==2023.7.22
cffi==1.15.1
charset-normalizer==3.2.0
configparser==6.0.0
constantly==15.1.0
contourpy==1.1.0
cryptography==41.0.3
cycler==0.11.0
fonttools==4.41.1
future==0.18.3
hyperlink==21.0.0
idna==3.4
importlib-resources==6.0.0
incremental==22.10.0
kiwisolver==1.4.4
matplotlib==3.7.2
memory-profiler==0.61.0
numpy==1.24.4
packaging==23.1
pika==1.3.2
Pillow==10.0.0
psutil==5.9.5
pyasn1==0.5.0
pyasn1-modules==0.3.0
pycparser==2.21
pylabrad==0.98.2
PyMySQL==1.1.0
pyOpenSSL==23.2.0
pyparsing==3.0.9
python-dateutil==2.8.2
pytz==2023.3
redis==3.5.3
redis-py-cluster==2.1.3
requests==2.31.0
schedule==1.2.0
scipy==1.10.1
service-identity==23.1.0
setproctitle==1.3.2
six==1.16.0
Twisted==22.10.0
typing-extensions==4.7.1
tzlocal==5.0.1
zope.interface==6.0
isqmap==0.4
sabreMapper==0.1.0
setuptools==41.2.0
9.2 混合程序¶
为减少用户的工作量,我们支持用户程序的直接运行。即用户在自己本地环境设计并验证程序后,需要高效的执行程序时,将相关程序打包,提交到runtime中运行即可。
因为用户有可能要使用本地数据,所以需要注意用户数据的绝对路径。用户程序运行时,相关数据目录关系如下:
/usr/src/app/ #用户的程序目录,即用户上传的文件会被解压到该目录,如果用户数据中有目录,也是基于该目录的。
对于该目录内容的引用,用户可以直接使用上述绝对地址,也可以引用相对于主文件的相对路径,即“./”
/usr/src/app/result/ #runtime模式最终返回的目录,即用户需要的计算结果,请都写入改目录,才能在程序执行结束后,拿到该目录中的结果。
如果用户要提前组织上面结果目录下的文件或目录结构,需要在代码中创建相应的目录。
不能提前在自己的上次文件包中创建相应的目录层级,因为result目录会被runtime机制覆盖,才能保证拿到最终的结果。
实际用例见如下示例。
import os
import json
from pyezQ import Account
account = Account('', '')
#用户已经有权利将程序已经传递到指定量子计算机,用户信息和机器选择可以不传。传递也不校验。
# 定义目录和文件名的前缀
directory = './submit_circuits_barrier_1207' # 替换为实际目录的路径
#以上为数据/线路来源目录
directory_r = './result/results_circuits_barrier_1207' # 替换为实际目录的路径
os.makedirs(directory_r, exist_ok=True)
#希望管理返回结果的结构,所以从新创建了相关目录、
#以上为线路结果保存目录
#以上两个都在用户上传目录为基础目录的位置。希望返回结果在改位置。
#目前的设计应该是智能返回目前开放的那个目录,不能返回用户上传的那个目录。
#我倒是觉得可以让这两个目录统一,用户不关心上传文件或下载数据的绝对位置,而是写到相对main函数的路径里。
#这样返回打包时,可以包用户运行的程序一起打包回来。
#甚至目前设置中的/usr/src/app/temp/目录都可以放到用户main目录里,但不知道文件会有多大。
prefix = 'QC_circuit_'
new_prefix = 'QC_results_'
# 获取目录下所有文件
files = os.listdir(directory)
# 遍历每个文件,提交并保存实验。
for file in files:
if file.startswith(prefix) and file.endswith('.txt'):
file_path = os.path.join(directory, file)
# 读取文件内容
with open(file_path, 'r') as f:
content = f.read()
query_id = account.submit_job(circuit=content,num_shots=10000, is_verify=False)
print(query_id)
# 打印文件内容
#print(content)
if query_id:
result=account.query_experiment(query_id, max_wait_time=360000)
# 构建新文件名
new_file = file.replace(prefix, new_prefix)
# 写入新文件
new_file_path = os.path.join(directory_r, new_file)
print('new_file_path:', new_file_path)
with open(new_file_path, 'w') as f:
json.dump(result, f)
print(f"File {file} processed and saved as {new_file}")
#以上是用户运行完量子程序,并保存了实验结果,上述过程没有直接利用结果,而是在以下运用结果的。
# 获取目录下所有文件
files = os.listdir(directory_r)
#从用户上传目录中读取文件参数
with open('heavy.json') as f:
all_heavy_outputs = json.load(f)
avg_HOP = 0
num_exp = 0
#这回是一个和量子实验无关的实验结果写会文件。
#因为中途的print用户看不见,所以结果,或者想print的文件,都可以写在专门的目录和文件中。
f = open('./result/result.txt', 'w')
# while True:
# pass
#for line in open('submit_log.txt'):
# 遍历每个文件
for name in files:
#name, exp_id = line.strip().split(' ')
assert name in all_heavy_outputs
num_exp += 1
heavy_outputs = all_heavy_outputs[name]
file_path = os.path.join(directory_r, name)
# 读取文件内容
with open(file_path, 'r') as fr:
content = json.load(fr)
content = content[0]
exp_probability = account.probability_calibration(content)
#注意,runtime模式的返回结果中不含有直接的统计概率,用户需要调用我们提供的函数进行计算。
#我们把不是全部用户都需要的功能节省下来,给用户争取时间。用户有需求时只需简单调用。
#这是运行runtime模式,唯一要注意的点。
HOP = 0
for state in heavy_outputs:
HOP += exp_probability[state]
print(f'{name}, HOP: {HOP:.2f}')
f.write(f'{name},{HOP:.2f}\n')
avg_HOP += HOP
avg_HOP /= num_exp
print(f'avg_HOP = {avg_HOP:.4f}')
f.write(f'avg_HOP,{avg_HOP:.4f}')
f.close()
9.3 数据打包与上传运行¶
将上述准备的文件进行打包为zip文件,文件结构如下:
|
+---Data
| \---data.dat (数据文件,可以在子目录内,可以是多个文件,目录和文件名自取)
|---main.py (主程序入口,文件名必须为main.py)
\---requirements.txt
请确保压缩文件的顶层不要有额外的目录,即确保main.py文件在压缩文件中的根目录下。
通过网站访问到runtime页面(量子计算实验室->高效融合计算),点击“新建融合任务”,在新页面中设置:
- 任务名称,用户可以自定义任务名称,系统会自动追加一个结尾,以便重复。
- 量子计算机,列表形式,只有支持runtime模式和正常服务的量子计算机被列出。
- 实验文件,上面准备的zip文件,注意只能上传zip文件,每次只能上传一个,如果需要调整,可以点击删除已经上传的文件,并重新上传,zip文件不超过10M。
- 使用内存资源,选择程序/环境运行时需要的最大内存,请合理预算资源,让更多人可以公平使用量子计算机。
- 最大运行时间,设置用户能接受的最长时间,主要是用于控制程序的意外死循环情况。
- 确定,任务被提交,进入runtime任务的排队流程,任务被运行会有状态更新。
9.4 下载结果¶
Runtime任务的返回条件是
- 程序无报错,自然结束。
- 设定时间到,服务器终止任务。
- 程序报错,异常结束。
这三种情况网页端都可以见到响应的结果,其中1,2都会正常返回resutlts目录,在网页端可以直接查看目录结构,查看文件内容。但不提示是自然结束还是服务器终止。
3则会只有一个报错文件,用户可以直接查看错误文件信息,并修改用户程序。
用户可以在网页端实验结果查看状态下,下载全部实验结果。