Z3 中的并行求解
Parallel solving in Z3
Z3 4.8.1 的新功能之一是并行求解:
A parallel mode is available for select theories, including QF_BV. By
setting parallel.enable=true Z3 will spawn a number of worker threads
proportional to the number of available CPU cores to apply cube and
conquer solving on the goal.
它提到只需要设置 parallel.enable=true
但我在代码中找不到 parallel
结构。
有人可以提供一些示例代码来了解如何实现这个新功能吗?
谢谢
简短回答: 正如@LeventErkok 指出的那样,parallel.enable=true
的语法用于 z3 可执行文件本身的命令行。正如他和 @Claies's link had indicated 所说,如果您使用的是绑定,则需要使用相关的 set_param()
方法。对于 C++,即 set_param("parallel.enable", true);
当我把这个添加到
C++ binding example,它给出了基本相同的输出...尽管它向 stderr 输出了一些额外的信息,比如一堆行:
(tactic.parallel :progress 0% :closed 0 :open 1)
(tactic.parallel :progress 100% :status sat :closed 0 :open 0)
这与@LeventErkrok 在另一个问题上使用 z3 工具观察到的差异相匹配。
It mentions that just parallel.enable=true needs to be set but I can't find that parallel structure in the code.
(我很好奇 Z3 是什么,所以我也去寻找 parallel.enable 的 C++ 源代码。所以这就是我的答案的起点,在知道更多的人之前回答。我的发现留在这里供任何感兴趣的人使用...)
长答案:如果您正在查看 z3 本身的源代码,您不会在其中找到名为 parallel
的 C++ object会写parallel.enable = true;
。它是一个 属性 存储在由字符串名称管理的配置 object 中。该配置 object 称为 parallel_params
,它不在 GitHub 中,因为它是作为构建过程的一部分生成的,进入 src/solver/parallel_params.hpp
这些属性及其默认值的规范在 .pyg
文件中 per-module。这只是构建准备过程加载的 Python 和 eval()'d with a few things defined. The parallel solver options are in src/solver/parallel_params.pyg
,例如:
def_module_params('parallel',
description='parameters for parallel solver',
class_name='parallel_params',
export=True,
params=(
('enable', BOOL, False, 'enable parallel solver ...'),
('threads.max', UINT, 10000, 'caps maximal number of threads ...'),
# ...etc.
如果你想在构建 z3 时更改这些默认值,看起来你必须编辑 .pyg
文件,因为似乎没有像 python scripts/mk_make.py parallel.enable=true
.
这样的参数化
作为更改此文件如何影响生成的 header 定义并行属性的示例,我直接将 parallel_params.pyg
修改为 "True" 而不是 "False" 因为它默认。结果是生成的 src/solver/parallel_params.hpp
文件的以下 2 行差异:
-- a/src/solver/parallel_params.hpp
+++ b/src/solver/parallel_params.hpp
@@ -9,7 +9,7 @@ struct parallel_params {
parallel_params(params_ref const & _p = params_ref::get_empty()):
p(_p), g(gparams::get_module("parallel")) {}
static void collect_param_descrs(param_descrs & d) {
- d.insert("enable", CPK_BOOL, "enable parallel solver by default on selected tactics (for QF_BV)", "false","parallel");
+ d.insert("enable", CPK_BOOL, "enable parallel solver by default on selected tactics (for QF_BV)", "true","parallel");
d.insert("threads.max", CPK_UINT, "caps maximal number of threads below the number of processors", "10000","parallel");
d.insert("conquer.batch_size", CPK_UINT, "number of cubes to batch together for fast conquer", "100","parallel");
d.insert("conquer.restart.max", CPK_UINT, "maximal number of restarts during conquer phase", "5","parallel");
@@ -23,7 +23,7 @@ struct parallel_params {
REG_MODULE_PARAMS('parallel', 'parallel_params::collect_param_descrs')
REG_MODULE_DESCRIPTION('parallel', 'parameters for parallel solver')
*/
- bool enable() const { return p.get_bool("enable", g, false); }
+ bool enable() const { return p.get_bool("enable", g, true); }
unsigned threads_max() const { return p.get_uint("threads.max", g, 10000u); }
unsigned conquer_batch_size() const { return p.get_uint("conquer.batch_size", g, 100u); }
unsigned conquer_restart_max() const { return p.get_uint("conquer.restart.max", g, 5u); }
从命令行
如果您使用的是 z3 可执行文件,那么您只需在命令行中传递设置即可。也就是说,如果您的脚本在文件 a.smt2
中,请使用:
z3 parallel.enable=true a.smt2
z3 将在处理基准时使用并行求解器。例如:
$ cat a.smt2
(set-logic QF_AUFBV )
(set-option :produce-models true)
(declare-fun a () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(assert (bvult a b))
(check-sat)
(get-model)
正常通话:
$ z3 a.smt2
sat
(model
(define-fun a () (_ BitVec 32)
#x00000000)
(define-fun b () (_ BitVec 32)
#x00000001)
)
并行模式:
$ z3 parallel.enable=true a.smt2
(tactic.parallel :progress 0% :closed 0 :open 1)
(tactic.parallel :progress 100% :status sat :closed 0 :open 0)
sat
(model
(define-fun a () (_ BitVec 32)
#x00000000)
(define-fun b () (_ BitVec 32)
#x00000001)
)
请注意关于第二个并行模式执行的额外注释 运行。
以编程方式
如果您问的是如何通过编程方式使用它 API?对于 Python,它看起来像:
from z3 import *
set_param('parallel.enable', True)
我确定其他 API 也有类似的电话。 (警告:我自己实际上 used/tested 这个功能;而且由于它是相当新的,可能并非所有程序化 API 都支持它。希望你得到一个不错的 warning/error 如果是这样的话!)
Z3 4.8.1 的新功能之一是并行求解:
A parallel mode is available for select theories, including QF_BV. By setting parallel.enable=true Z3 will spawn a number of worker threads proportional to the number of available CPU cores to apply cube and conquer solving on the goal.
它提到只需要设置 parallel.enable=true
但我在代码中找不到 parallel
结构。
有人可以提供一些示例代码来了解如何实现这个新功能吗?
谢谢
简短回答: 正如@LeventErkok 指出的那样,parallel.enable=true
的语法用于 z3 可执行文件本身的命令行。正如他和 @Claies's link had indicated 所说,如果您使用的是绑定,则需要使用相关的 set_param()
方法。对于 C++,即 set_param("parallel.enable", true);
当我把这个添加到 C++ binding example,它给出了基本相同的输出...尽管它向 stderr 输出了一些额外的信息,比如一堆行:
(tactic.parallel :progress 0% :closed 0 :open 1)
(tactic.parallel :progress 100% :status sat :closed 0 :open 0)
这与@LeventErkrok 在另一个问题上使用 z3 工具观察到的差异相匹配。
It mentions that just parallel.enable=true needs to be set but I can't find that parallel structure in the code.
(我很好奇 Z3 是什么,所以我也去寻找 parallel.enable 的 C++ 源代码。所以这就是我的答案的起点,在知道更多的人之前回答。我的发现留在这里供任何感兴趣的人使用...)
长答案:如果您正在查看 z3 本身的源代码,您不会在其中找到名为 parallel
的 C++ object会写parallel.enable = true;
。它是一个 属性 存储在由字符串名称管理的配置 object 中。该配置 object 称为 parallel_params
,它不在 GitHub 中,因为它是作为构建过程的一部分生成的,进入 src/solver/parallel_params.hpp
这些属性及其默认值的规范在 .pyg
文件中 per-module。这只是构建准备过程加载的 Python 和 eval()'d with a few things defined. The parallel solver options are in src/solver/parallel_params.pyg
,例如:
def_module_params('parallel',
description='parameters for parallel solver',
class_name='parallel_params',
export=True,
params=(
('enable', BOOL, False, 'enable parallel solver ...'),
('threads.max', UINT, 10000, 'caps maximal number of threads ...'),
# ...etc.
如果你想在构建 z3 时更改这些默认值,看起来你必须编辑 .pyg
文件,因为似乎没有像 python scripts/mk_make.py parallel.enable=true
.
作为更改此文件如何影响生成的 header 定义并行属性的示例,我直接将 parallel_params.pyg
修改为 "True" 而不是 "False" 因为它默认。结果是生成的 src/solver/parallel_params.hpp
文件的以下 2 行差异:
-- a/src/solver/parallel_params.hpp
+++ b/src/solver/parallel_params.hpp
@@ -9,7 +9,7 @@ struct parallel_params {
parallel_params(params_ref const & _p = params_ref::get_empty()):
p(_p), g(gparams::get_module("parallel")) {}
static void collect_param_descrs(param_descrs & d) {
- d.insert("enable", CPK_BOOL, "enable parallel solver by default on selected tactics (for QF_BV)", "false","parallel");
+ d.insert("enable", CPK_BOOL, "enable parallel solver by default on selected tactics (for QF_BV)", "true","parallel");
d.insert("threads.max", CPK_UINT, "caps maximal number of threads below the number of processors", "10000","parallel");
d.insert("conquer.batch_size", CPK_UINT, "number of cubes to batch together for fast conquer", "100","parallel");
d.insert("conquer.restart.max", CPK_UINT, "maximal number of restarts during conquer phase", "5","parallel");
@@ -23,7 +23,7 @@ struct parallel_params {
REG_MODULE_PARAMS('parallel', 'parallel_params::collect_param_descrs')
REG_MODULE_DESCRIPTION('parallel', 'parameters for parallel solver')
*/
- bool enable() const { return p.get_bool("enable", g, false); }
+ bool enable() const { return p.get_bool("enable", g, true); }
unsigned threads_max() const { return p.get_uint("threads.max", g, 10000u); }
unsigned conquer_batch_size() const { return p.get_uint("conquer.batch_size", g, 100u); }
unsigned conquer_restart_max() const { return p.get_uint("conquer.restart.max", g, 5u); }
从命令行
如果您使用的是 z3 可执行文件,那么您只需在命令行中传递设置即可。也就是说,如果您的脚本在文件 a.smt2
中,请使用:
z3 parallel.enable=true a.smt2
z3 将在处理基准时使用并行求解器。例如:
$ cat a.smt2
(set-logic QF_AUFBV )
(set-option :produce-models true)
(declare-fun a () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(assert (bvult a b))
(check-sat)
(get-model)
正常通话:
$ z3 a.smt2
sat
(model
(define-fun a () (_ BitVec 32)
#x00000000)
(define-fun b () (_ BitVec 32)
#x00000001)
)
并行模式:
$ z3 parallel.enable=true a.smt2
(tactic.parallel :progress 0% :closed 0 :open 1)
(tactic.parallel :progress 100% :status sat :closed 0 :open 0)
sat
(model
(define-fun a () (_ BitVec 32)
#x00000000)
(define-fun b () (_ BitVec 32)
#x00000001)
)
请注意关于第二个并行模式执行的额外注释 运行。
以编程方式
如果您问的是如何通过编程方式使用它 API?对于 Python,它看起来像:
from z3 import *
set_param('parallel.enable', True)
我确定其他 API 也有类似的电话。 (警告:我自己实际上 used/tested 这个功能;而且由于它是相当新的,可能并非所有程序化 API 都支持它。希望你得到一个不错的 warning/error 如果是这样的话!)