Skip to content

Commit e366dfb

Browse files
committed
Squash and merges #748: first version of PEx parallel
1 parent c150243 commit e366dfb

20 files changed

+887
-217
lines changed

Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/RuntimeExecutor.java

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pexplicit.runtime.STATUS;
55
import pexplicit.runtime.logger.PExplicitLogger;
66
import pexplicit.runtime.logger.StatWriter;
7+
import pexplicit.runtime.scheduler.Scheduler;
78
import pexplicit.runtime.scheduler.explicit.ExplicitSearchScheduler;
89
import pexplicit.runtime.scheduler.replay.ReplayScheduler;
910
import pexplicit.utils.exceptions.BugFoundException;
@@ -14,25 +15,35 @@
1415

1516
import java.time.Duration;
1617
import java.time.Instant;
18+
import java.util.ArrayList;
1719
import java.util.concurrent.*;
1820

1921
/**
2022
* Represents the runtime executor that executes the analysis engine
2123
*/
2224
public class RuntimeExecutor {
23-
private static ExecutorService executor;
24-
private static Future<Integer> future;
25-
private static ExplicitSearchScheduler scheduler;
25+
private static ThreadPoolExecutor executor;
26+
private static ArrayList<Future<Integer>> futures = new ArrayList<>();
27+
private static ArrayList<ExplicitSearchScheduler> schedulers = new ArrayList<>();
2628

2729
private static void runWithTimeout(long timeLimit)
2830
throws TimeoutException,
2931
InterruptedException,
3032
RuntimeException {
31-
try {
33+
try { // PIN: If thread gets exception, need to kill the other threads.
3234
if (timeLimit > 0) {
33-
future.get(timeLimit, TimeUnit.SECONDS);
35+
36+
for (Future<Integer> future : futures) {
37+
// Future<Integer> future = futures.get(i);
38+
future.get(timeLimit, TimeUnit.SECONDS);
39+
}
40+
3441
} else {
35-
future.get();
42+
43+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++) {
44+
Future<Integer> future = futures.get(i);
45+
future.get();
46+
}
3647
}
3748
} catch (TimeoutException | BugFoundException e) {
3849
throw e;
@@ -55,7 +66,11 @@ private static void runWithTimeout(long timeLimit)
5566

5667
private static void printStats() {
5768
double searchTime = TimeMonitor.stopInterval();
58-
scheduler.recordStats();
69+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++) {
70+
ExplicitSearchScheduler scheduler = schedulers.get(i);
71+
scheduler.recordStats();
72+
}
73+
5974
if (PExplicitGlobal.getResult().equals("correct for any depth")) {
6075
PExplicitGlobal.setStatus(STATUS.VERIFIED);
6176
} else if (PExplicitGlobal.getResult().startsWith("correct up to step")) {
@@ -69,9 +84,9 @@ private static void preprocess() {
6984
PExplicitLogger.logInfo(String.format("... Checker is using '%s' strategy (seed:%s)",
7085
PExplicitGlobal.getConfig().getSearchStrategyMode(), PExplicitGlobal.getConfig().getRandomSeed()));
7186

72-
executor = Executors.newSingleThreadExecutor();
87+
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(PExplicitGlobal.getMaxThreads());
7388

74-
PExplicitGlobal.setResult("error");
89+
// PExplicitGlobal.setResult("error"); // TODO: Set Results, need to take care of.
7590

7691
double preSearchTime =
7792
TimeMonitor.findInterval(TimeMonitor.getStart());
@@ -84,10 +99,29 @@ private static void preprocess() {
8499

85100
private static void process(boolean resume) throws Exception {
86101
try {
87-
TimedCall timedCall = new TimedCall(scheduler, resume);
88-
future = executor.submit(timedCall);
102+
// create and add first task through scheduler 0
103+
schedulers.get(0).getSearchStrategy().createFirstTask();
104+
105+
ArrayList<TimedCall> timedCalls = new ArrayList<>();
106+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++) {
107+
timedCalls.add(new TimedCall(schedulers.get(i), resume, i));
108+
}
109+
110+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++) {
111+
Future<Integer> future = executor.submit(timedCalls.get(i));
112+
futures.add(future);
113+
}
114+
115+
Thread.sleep(1000); // Sleep for 1 second, so that threads can pick up the task from the executor object
116+
117+
// Get the number of pending tasks
118+
int pendingTasks = executor.getQueue().size();
119+
PExplicitLogger.logInfo("Number of pending tasks: " + pendingTasks);
120+
89121
TimeMonitor.startInterval();
122+
90123
runWithTimeout((long) PExplicitGlobal.getConfig().getTimeLimit());
124+
91125
} catch (TimeoutException e) {
92126
PExplicitGlobal.setStatus(STATUS.TIMEOUT);
93127
throw new Exception("TIMEOUT", e);
@@ -96,13 +130,21 @@ private static void process(boolean resume) throws Exception {
96130
throw new Exception("MEMOUT", e);
97131
} catch (BugFoundException e) {
98132
PExplicitGlobal.setStatus(STATUS.BUG_FOUND);
99-
PExplicitGlobal.setResult(String.format("found cex of length %d", scheduler.getStepNumber()));
133+
134+
100135
PExplicitLogger.logStackTrace(e);
101136

102-
ReplayScheduler replayer = new ReplayScheduler(scheduler.schedule);
103-
PExplicitGlobal.setScheduler(replayer);
137+
ArrayList<ReplayScheduler> replayers = new ArrayList<>();
138+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++)
139+
replayers.add(new ReplayScheduler((schedulers.get(i)).schedule));
140+
141+
ArrayList<Scheduler> localSchedulers = PExplicitGlobal.getSchedulers();
142+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++)
143+
localSchedulers.set(i, replayers.get(i));
144+
104145
try {
105-
replayer.run();
146+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++)
147+
(replayers.get(i)).run();
106148
} catch (NullPointerException | StackOverflowError | ClassCastException replayException) {
107149
PExplicitLogger.logStackTrace((Exception) replayException);
108150
throw new BugFoundException(replayException.getMessage(), replayException);
@@ -121,20 +163,34 @@ private static void process(boolean resume) throws Exception {
121163
PExplicitGlobal.setStatus(STATUS.ERROR);
122164
throw new Exception("ERROR", e);
123165
} finally {
124-
future.cancel(true);
166+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++) {
167+
Future<Integer> future = futures.get(i);
168+
future.cancel(true);
169+
}
125170
executor.shutdownNow();
126-
scheduler.updateResult();
171+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++)
172+
(schedulers.get(i)).updateResult();
127173
printStats();
128-
PExplicitLogger.logEndOfRun(scheduler, Duration.between(TimeMonitor.getStart(), Instant.now()).getSeconds());
174+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++)
175+
PExplicitLogger.logEndOfRun(schedulers.get(i), Duration.between(TimeMonitor.getStart(), Instant.now()).getSeconds());
129176
}
130177
}
131178

132179
public static void run() throws Exception {
133-
scheduler = new ExplicitSearchScheduler();
134-
PExplicitGlobal.setScheduler(scheduler);
180+
ArrayList<Scheduler> localSchedulers = PExplicitGlobal.getSchedulers();
181+
for (int i = 0; i < PExplicitGlobal.getMaxThreads(); i++) {
182+
ExplicitSearchScheduler localCopy = new ExplicitSearchScheduler();
183+
schedulers.add(localCopy);
184+
localSchedulers.add(localCopy);
185+
}
186+
135187

136188
preprocess();
189+
190+
137191
process(false);
192+
193+
138194
}
139195

140196
}

Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
*/
1212
@Getter
1313
public class PExplicitConfig {
14+
@Getter
15+
@Setter
16+
private static int numThreads = 1;
1417
// default name of the test driver
1518
final String testDriverDefault = "DefaultImpl";
1619
// name of the test driver
@@ -64,4 +67,5 @@ public class PExplicitConfig {
6467
//max number of children search tasks
6568
@Setter
6669
int maxChildrenPerTask = 2;
70+
6771
}

Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitOptions.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,16 @@ public class PExplicitOptions {
148148
.build();
149149
addOption(randomSeed);
150150

151-
151+
// Number of threads
152+
Option numThreads =
153+
Option.builder()
154+
.longOpt("nproc")
155+
.desc("Specify the number of threads to use")
156+
.numberOfArgs(1)
157+
.hasArg()
158+
.argName("No. of threads (integer)")
159+
.build();
160+
addOption(numThreads);
152161
/*
153162
* Invisible/expert options
154163
*/
@@ -336,6 +345,9 @@ public static PExplicitConfig ParseCommandlineArgs(String[] args) {
336345
option, String.format("Expected an integer value, got %s", option.getValue()));
337346
}
338347
break;
348+
case "nproc":
349+
PExplicitConfig.setNumThreads(Integer.parseInt(option.getValue()));
350+
break;
339351
// invisible expert options
340352
case "state-caching":
341353
switch (option.getValue()) {

Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/ForeignFunctionInterface.java

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,24 @@
55
import java.util.function.Function;
66

77
public class ForeignFunctionInterface {
8-
/**
9-
* Invoke a foreign function with a void return type
10-
*
11-
* @param fn function to invoke
12-
* @param args arguments
13-
*/
14-
public static void accept(Consumer<List<Object>> fn, Object... args) {
15-
fn.accept(List.of(args));
16-
}
8+
/**
9+
* Invoke a foreign function with a void return type
10+
*
11+
* @param fn function to invoke
12+
* @param args arguments
13+
*/
14+
public static void accept(Consumer<List<Object>> fn, Object... args) {
15+
fn.accept(List.of(args));
16+
}
1717

18-
/**
19-
* Invoke a foreign function with a non-void return type
20-
*
21-
* @param fn function to invoke
22-
* @param args arguments
23-
* @return the return value of the function
24-
*/
25-
public static Object apply(Function<List<Object>, Object> fn, Object... args) {
26-
return fn.apply(List.of(args));
27-
}
18+
/**
19+
* Invoke a foreign function with a non-void return type
20+
*
21+
* @param fn function to invoke
22+
* @param args arguments
23+
* @return the return value of the function
24+
*/
25+
public static Object apply(Function<List<Object>, Object> fn, Object... args) {
26+
return fn.apply(List.of(args));
27+
}
2828
}

0 commit comments

Comments
 (0)