Skip to content

Commit c06fe3b

Browse files
committed
scheduler sequential option
1 parent 01bbda9 commit c06fe3b

File tree

2 files changed

+73
-17
lines changed

2 files changed

+73
-17
lines changed

include/dbscan/pbbs/parallel.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,26 +139,38 @@ namespace parlay {
139139
get_default_scheduler().stop();
140140
}
141141
}
142+
inline bool sequential = false;
142143

143144
inline size_t num_workers() {
144-
return internal::get_default_scheduler().num_workers();
145+
return sequential ? 1u : internal::get_default_scheduler().num_workers();
145146
}
146147

147148
inline size_t worker_id() {
148-
return internal::get_default_scheduler().worker_id();
149+
return sequential ? 0u : internal::get_default_scheduler().worker_id();
149150
}
150151

151152
template <class F>
152153
inline void parallel_for(size_t start, size_t end, F f,
153154
size_t granularity=0,
154155
bool conservative=false) {
155-
if (end > start)
156-
internal::get_default_scheduler().parfor(start, end, f, granularity, conservative);
156+
if (end > start){
157+
if (sequential){
158+
for(size_t i=start; i<end; ++i) f(i);
159+
}
160+
else{
161+
internal::get_default_scheduler().parfor(start, end, f, granularity, conservative);
162+
}
163+
}
157164
}
158165

159166
template <typename Lf, typename Rf>
160167
inline void par_do(Lf left, Rf right, bool conservative=false) {
161-
return internal::get_default_scheduler().pardo(left, right, conservative);
168+
if (sequential) {
169+
left(); right();
170+
}
171+
else {
172+
internal::get_default_scheduler().pardo(left, right, conservative);
173+
}
162174
}
163175
}
164176

@@ -171,8 +183,8 @@ using namespace parlay;
171183
#define par_for_1 for
172184
#define par_for_256 for
173185

174-
static int getWorkers() {return (int)num_workers();}
175-
static int getWorkerId() {return (int)worker_id();}
186+
static int getWorkers() {return sequential ? 1 : (int)num_workers();}
187+
static int getWorkerId() {return sequential ? 0 : (int)worker_id();}
176188
static void setWorkers(int n) { }
177189
static void printScheduler() {
178190
cout << "scheduler = Parlay-HomeGrown" << endl;

src/dbscanmodule.cpp

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
static bool scheduler_initialized = false;
88
static PyObject* scheduler_cleanup_weakref = nullptr;
99

10-
static void cleanup_scheduler(PyObject *capsule)
10+
static void cleanup_scheduler(PyObject *capsule=nullptr)
1111
{
12-
if (scheduler_initialized)
13-
{
14-
parlay::internal::stop_scheduler();
15-
scheduler_initialized = false;
16-
}
12+
if (scheduler_initialized)
13+
{
14+
parlay::internal::stop_scheduler();
15+
scheduler_initialized = false;
16+
}
1717
}
1818

1919
static void ensure_scheduler_initialized()
@@ -40,7 +40,7 @@ static PyObject* DBSCAN_py(PyObject* self, PyObject* args, PyObject *kwargs)
4040
return NULL;
4141
}
4242

43-
// Check the number of dimensions and that we actually recieved an np.ndarray
43+
// Check the number of dimensions and that we actually received an np.ndarray
4444
X = (PyArrayObject*)PyArray_FROMANY(
4545
Xobj,
4646
NPY_DOUBLE,
@@ -79,7 +79,10 @@ static PyObject* DBSCAN_py(PyObject* self, PyObject* args, PyObject *kwargs)
7979
PyArrayObject* core_samples = (PyArrayObject*)PyArray_SimpleNew(1, &n, NPY_BOOL);
8080
PyArrayObject* labels = (PyArrayObject*)PyArray_SimpleNew(1, &n, NPY_INT);
8181

82-
ensure_scheduler_initialized();
82+
if (!parlay::sequential)
83+
{
84+
ensure_scheduler_initialized();
85+
}
8386

8487
DBSCAN(
8588
dim,
@@ -98,9 +101,27 @@ static PyObject* DBSCAN_py(PyObject* self, PyObject* args, PyObject *kwargs)
98101
return result_tuple;
99102
}
100103

104+
static PyObject* set_sequential_py(PyObject* self, PyObject* args)
105+
{
106+
int state = 1;
107+
if (!PyArg_ParseTuple(args, "|p", &state)) {
108+
return nullptr;
109+
}
110+
parlay::sequential = state == 1;
111+
if (parlay::sequential) {
112+
cleanup_scheduler();
113+
}
114+
Py_RETURN_NONE;
115+
}
116+
117+
static PyObject* get_sequential_py(PyObject* self, PyObject* args)
118+
{
119+
return PyBool_FromLong(parlay::sequential ? 1 : 0);
120+
}
121+
101122
PyDoc_STRVAR(doc_DBSCAN,
102123
"DBSCAN(X, eps=0.5, min_samples=5)\n--\n\n\
103-
Run DBSCAN on a set of n samples of dimension dim with a minimum seperation\n\
124+
Run DBSCAN on a set of n samples of dimension dim with a minimum separation\n\
104125
between the clusters (which must include at least min_samples) of eps. Points\n\
105126
that do not fit in any cluster are labeled as noise (-1).\n\
106127
\n\
@@ -113,7 +134,7 @@ Parameters\n\
113134
X : np.ndarray[tuple[n, dim], np.float64]\n\
114135
2-D array representing the samples.\n\
115136
eps : float\n\
116-
minimum seperation between the clusters.\n\
137+
minimum separation between the clusters.\n\
117138
min_samples : int\n\
118139
minimum number of samples in the clusters.\n\
119140
\n\
@@ -125,8 +146,31 @@ core_samples : np.ndarray[tuple[n], np.bool_]\n\
125146
is each sample the core sample of its cluster\n\
126147
\n");
127148

149+
PyDoc_STRVAR(doc_set_sequential,
150+
"set_sequential(state=True)\n--\n\n\
151+
Set whether DBSCAN runs in sequential mode (single-threaded).\n\
152+
This mode is potentially more efficient.\n\
153+
\n\
154+
Parameters\n\
155+
----------\n\
156+
state : bool, default True\n\
157+
If True, run sequentially. If False, allow parallel execution.\n\
158+
");
159+
160+
PyDoc_STRVAR(doc_get_sequential,
161+
"get_sequential()\n--\n\n\
162+
Return the current state of the sequential setting.\n\
163+
\n\
164+
Returns\n\
165+
-------\n\
166+
state : bool\n\
167+
True if running sequentially, False if in parallel mode.\n\
168+
");
169+
128170
static struct PyMethodDef methods[] = {
129171
{"DBSCAN", (PyCFunction)(void*)(PyCFunctionWithKeywords) DBSCAN_py, METH_VARARGS | METH_KEYWORDS, doc_DBSCAN},
172+
{"set_sequential", (PyCFunction)set_sequential_py, METH_VARARGS, doc_set_sequential},
173+
{"get_sequential", (PyCFunction)get_sequential_py, METH_NOARGS, doc_get_sequential},
130174
{NULL, NULL, 0, NULL}
131175
};
132176

0 commit comments

Comments
 (0)