Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ jobs:

steps:
- checkout
- run: git submodule sync
- run: git submodule update --init
- setup_remote_docker
- restore_cache: &build-linux-restore-cache
keys:
Expand Down Expand Up @@ -61,6 +63,8 @@ jobs:

steps: &build-steps
- checkout
- run: git submodule sync
- run: git submodule update --init
- restore_cache: *build-linux-restore-cache
- run: *build-linux-wheels
- save_cache: *build-linux-save-cache
Expand Down Expand Up @@ -90,6 +94,8 @@ jobs:

steps:
- checkout
- run: git submodule sync
- run: git submodule update --init
- run:
name: build sdist
command: |
Expand All @@ -115,6 +121,8 @@ jobs:

steps:
- checkout
- run: git submodule sync
- run: git submodule update --init
- run:
name: build wheels
command: |
Expand Down Expand Up @@ -152,6 +160,8 @@ jobs:

steps:
- checkout
- run: git submodule sync
- run: git submodule update --init
- run:
name: install dependencies
command: |
Expand Down Expand Up @@ -181,6 +191,8 @@ jobs:

steps:
- checkout
- run: git submodule sync
- run: git submodule update --init
- run:
name: install doxygen
command: sudo apt-get install doxygen
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
path = testscpp/Catch2
url = https://github.com/catchorg/Catch2.git
branch = v2.x
[submodule "extern/taskflow"]
path = extern/taskflow
url = [email protected]:taskflow/taskflow.git
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include pyproject.toml
recursive-include dwave/preprocessing/include/ *.hpp *.h
recursive-include dwave/preprocessing *.pyx *.pxd *.pyx.src
graft extern/taskflow/taskflow
include extern/taskflow/LICENSE
21 changes: 20 additions & 1 deletion dwave/preprocessing/include/dwave/presolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@

#pragma once

#include <chrono>
#include <thread>


#include <algorithm>
#include <unordered_map>
#include <utility>
#include <vector>

#include "dimod/constrained_quadratic_model.h"
#include <dimod/constrained_quadratic_model.h>
#include <taskflow/taskflow.hpp>

namespace dwave {
namespace presolve {
Expand Down Expand Up @@ -134,10 +139,24 @@ class Presolver {
/// Apply any loaded presolve techniques. Acts of the model() in-place.
void apply();

void apply_parallel() {
tf::Executor executor;
tf::Taskflow taskflow;

taskflow.for_each_index(0, static_cast<int>(model_.num_constraints()), 1,
[&](int i) { do_slow_thing(i); });

executor.run(taskflow).wait();
}

/// Detach the constrained quadratic model and return it.
/// This clears the model from the presolver.
model_type detach_model();

void do_slow_thing(index_type c) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}

/// Load the default presolve techniques.
void load_default_presolvers();

Expand Down
1 change: 1 addition & 0 deletions dwave/preprocessing/libcpp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ cdef extern from "dwave/presolve.h" namespace "dwave::presolve" nogil:
Presolver()
Presolver(model_type)
void apply() except+
void apply_parallel() except+
model_type detach_model()
void load_default_presolvers()
model_type& model()
Expand Down
7 changes: 7 additions & 0 deletions dwave/preprocessing/presolve/cypresolve.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ cdef class cyPresolver:
self.cpppresolver.apply()
self._model_num_variables = self.cpppresolver.model().num_variables()

def apply_parallel(self):
import time

t = time.perf_counter()
self.cpppresolver.apply_parallel()
return time.perf_counter() - t

def clear_model(self):
"""Clear the held model. This is useful to save memory."""
self.cpppresolver.detach_model()
Expand Down
1 change: 1 addition & 0 deletions extern/taskflow
Submodule taskflow added at f1490f
15 changes: 4 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,8 @@
from distutils.command.build_ext import build_ext as _build_ext

extra_compile_args = {
'msvc': ['/EHsc'],
'unix': ['-std=c++11'],
}

extra_link_args = {
'msvc': [],
'unix': ['-std=c++11'],
'msvc': ['/std:c++17', '/EHsc'],
'unix': ['-std=c++17', '-pthread'],
}


Expand All @@ -41,12 +36,9 @@ def build_extensions(self):
for ext in self.extensions:
ext.extra_compile_args.extend(compile_args)

link_args = extra_link_args[compiler]
for ext in self.extensions:
ext.extra_compile_args.extend(link_args)

super().build_extensions()


setup(
name='dwave-preprocessing',
cmdclass=dict(build_ext=build_ext),
Expand All @@ -60,6 +52,7 @@ def build_extensions(self):
include_dirs=[
numpy.get_include(),
dimod.get_include(),
"extern/taskflow/",
],
install_requires=[
'numpy>=1.20.0,<2.0.0', # keep synced with circle-ci, pyproject.toml
Expand Down
10 changes: 10 additions & 0 deletions tests/test_presolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
from dwave.preprocessing import Presolver, InfeasibleModelError


class TestExperiment(unittest.TestCase):
def test_parallel(self):
cqm = dimod.CQM()
for _ in range(100):
cqm.add_constraint(dimod.BQM("BINARY") == 1)

presolver = Presolver(cqm)
self.assertLessEqual(presolver.apply_parallel(), 55) # should take 100s


class TestPresolver(unittest.TestCase):
def test_bug0(self):
random = np.random.RandomState(0)
Expand Down
9 changes: 5 additions & 4 deletions testscpp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ ROOT := ../
SRC := $(ROOT)/dwave/preprocessing/
CATCH2 := $(ROOT)/testscpp/Catch2/single_include/
DIMOD := $(shell python -c 'import dimod; print(dimod.get_include())')
TASKFLOW := $(ROOT)/extern/taskflow/

all: catch2 test_main test_main_parallel tests tests_parallel

Expand All @@ -12,12 +13,12 @@ tests_parallel: test_main_parallel.out
./test_main_parallel

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

test_main_parallel: test_main.cpp
g++ -std=c++11 -fopenmp -Wall -c test_main.cpp -o test_main_parallel.o
g++ -std=c++11 -fopenmp -Wall test_main_parallel.o tests/*.cpp -o test_main_parallel -I $(SRC)/include/ -I $(DIMOD) -I $(CATCH2)
g++ -std=c++17 -fopenmp -Wall -c test_main.cpp -o test_main_parallel.o
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)

catch2:
git submodule init
Expand Down
10 changes: 10 additions & 0 deletions testscpp/tests/test_presolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,14 @@ SCENARIO("constrained quadratic models can be presolved") {
}
}

TEST_CASE("experiment") {
GIVEN("a CQM with a bunch of constraints") {
auto cqm = dimod::ConstrainedQuadraticModel<double>();
cqm.add_constraints(10);

auto presolver = presolve::Presolver<double>(std::move(cqm));
presolver.apply_parallel();
}
}

} // namespace dwave