Skip to content

Commit 867b21c

Browse files
committed
Experiment with using taskflow for parallel presolving
1 parent ad18c37 commit 867b21c

File tree

10 files changed

+63
-8
lines changed

10 files changed

+63
-8
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
path = testscpp/Catch2
33
url = https://github.com/catchorg/Catch2.git
44
branch = v2.x
5+
[submodule "extern/taskflow"]
6+
path = extern/taskflow
7+
url = git@github.com:taskflow/taskflow.git

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
include pyproject.toml
22
recursive-include dwave/preprocessing/include/ *.hpp *.h
33
recursive-include dwave/preprocessing *.pyx *.pxd *.pyx.src
4+
graft extern/taskflow/taskflow
5+
include extern/taskflow/LICENSE

dwave/preprocessing/include/dwave/presolve.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414

1515
#pragma once
1616

17+
#include <chrono>
18+
#include <thread>
19+
20+
1721
#include <algorithm>
1822
#include <unordered_map>
1923
#include <utility>
2024
#include <vector>
2125

22-
#include "dimod/constrained_quadratic_model.h"
26+
#include <dimod/constrained_quadratic_model.h>
27+
#include <taskflow/taskflow.hpp>
2328

2429
namespace dwave {
2530
namespace presolve {
@@ -134,10 +139,24 @@ class Presolver {
134139
/// Apply any loaded presolve techniques. Acts of the model() in-place.
135140
void apply();
136141

142+
void apply_parallel() {
143+
tf::Executor executor;
144+
tf::Taskflow taskflow;
145+
146+
taskflow.for_each_index(0, static_cast<int>(model_.num_constraints()), 1,
147+
[&](int i) { do_slow_thing(i); });
148+
149+
executor.run(taskflow).wait();
150+
}
151+
137152
/// Detach the constrained quadratic model and return it.
138153
/// This clears the model from the presolver.
139154
model_type detach_model();
140155

156+
void do_slow_thing(index_type c) {
157+
std::this_thread::sleep_for(std::chrono::seconds(1));
158+
}
159+
141160
/// Load the default presolve techniques.
142161
void load_default_presolvers();
143162

dwave/preprocessing/libcpp.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ cdef extern from "dwave/presolve.h" namespace "dwave::presolve" nogil:
2929
Presolver()
3030
Presolver(model_type)
3131
void apply() except+
32+
void apply_parallel() except+
3233
model_type detach_model()
3334
void load_default_presolvers()
3435
model_type& model()

dwave/preprocessing/presolve/cypresolve.pyx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ cdef class cyPresolver:
4747
self.cpppresolver.apply()
4848
self._model_num_variables = self.cpppresolver.model().num_variables()
4949

50+
def apply_parallel(self):
51+
import time
52+
53+
t = time.perf_counter()
54+
self.cpppresolver.apply_parallel()
55+
return time.perf_counter() - t
56+
5057
def clear_model(self):
5158
"""Clear the held model. This is useful to save memory."""
5259
self.cpppresolver.detach_model()

extern/taskflow

Submodule taskflow added at f1490ff

setup.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
from distutils.command.build_ext import build_ext as _build_ext
2424

2525
extra_compile_args = {
26-
'msvc': ['/EHsc'],
27-
'unix': ['-std=c++11'],
26+
'msvc': ['/EHsc', '-pthread'],
27+
'unix': ['-std=c++17', '-pthread'],
2828
}
2929

3030
extra_link_args = {
3131
'msvc': [],
32-
'unix': ['-std=c++11'],
32+
'unix': ['-std=c++17'],
3333
}
3434

3535

@@ -60,6 +60,7 @@ def build_extensions(self):
6060
include_dirs=[
6161
numpy.get_include(),
6262
dimod.get_include(),
63+
"extern/taskflow/",
6364
],
6465
install_requires=[
6566
'numpy>=1.20.0,<2.0.0', # keep synced with circle-ci, pyproject.toml

tests/test_presolve.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020
from dwave.preprocessing import Presolver, InfeasibleModelError
2121

2222

23+
class TestExperiment(unittest.TestCase):
24+
def test_parallel(self):
25+
cqm = dimod.CQM()
26+
for _ in range(100):
27+
cqm.add_constraint(dimod.BQM("BINARY") == 1)
28+
29+
presolver = Presolver(cqm)
30+
self.assertLessEqual(presolver.apply_parallel(), 55) # should take 100s
31+
32+
2333
class TestPresolver(unittest.TestCase):
2434
def test_bug0(self):
2535
random = np.random.RandomState(0)

testscpp/Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ ROOT := ../
22
SRC := $(ROOT)/dwave/preprocessing/
33
CATCH2 := $(ROOT)/testscpp/Catch2/single_include/
44
DIMOD := $(shell python -c 'import dimod; print(dimod.get_include())')
5+
TASKFLOW := $(ROOT)/extern/taskflow/
56

67
all: catch2 test_main test_main_parallel tests tests_parallel
78

@@ -12,12 +13,12 @@ tests_parallel: test_main_parallel.out
1213
./test_main_parallel
1314

1415
test_main: test_main.cpp
15-
g++ -std=c++11 -Wall -c test_main.cpp
16-
g++ -std=c++11 -Wall test_main.o tests/*.cpp -o test_main -I $(SRC)/include/ -I $(DIMOD) -I $(CATCH2)
16+
g++ -std=c++17 -Wall -pthread -c test_main.cpp
17+
g++ -std=c++17 -Wall -pthread test_main.o tests/*.cpp -o test_main -I $(SRC)/include/ -I $(DIMOD) -I $(CATCH2) -I $(TASKFLOW)
1718

1819
test_main_parallel: test_main.cpp
19-
g++ -std=c++11 -fopenmp -Wall -c test_main.cpp -o test_main_parallel.o
20-
g++ -std=c++11 -fopenmp -Wall test_main_parallel.o tests/*.cpp -o test_main_parallel -I $(SRC)/include/ -I $(DIMOD) -I $(CATCH2)
20+
g++ -std=c++17 -fopenmp -Wall -c test_main.cpp -o test_main_parallel.o
21+
g++ -std=c++17 -fopenmp -Wall test_main_parallel.o tests/*.cpp -o test_main_parallel -I $(SRC)/include/ -I $(DIMOD) -I $(CATCH2) -I $(TASKFLOW)
2122

2223
catch2:
2324
git submodule init

testscpp/tests/test_presolve.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,14 @@ SCENARIO("constrained quadratic models can be presolved") {
350350
}
351351
}
352352

353+
TEST_CASE("experiment") {
354+
GIVEN("a CQM with a bunch of constraints") {
355+
auto cqm = dimod::ConstrainedQuadraticModel<double>();
356+
cqm.add_constraints(10);
357+
358+
auto presolver = presolve::Presolver<double>(std::move(cqm));
359+
presolver.apply_parallel();
360+
}
361+
}
362+
353363
} // namespace dwave

0 commit comments

Comments
 (0)