}
private void execUpdates(final GraphChiProgram<VertexDataType, EdgeDataType> program,
final ChiVertex<VertexDataType, EdgeDataType>[] vertices) {
if (vertices == null || vertices.length == 0) return;
TimerContext _timer = executionTimer.time();
if (Runtime.getRuntime().availableProcessors() == 1) {
/* Sequential updates */
for(ChiVertex<VertexDataType, EdgeDataType> vertex : vertices) {
if (vertex != null) {
nupdates++;
program.update(vertex, chiContext);
}
}
} else {
final Object termlock = new Object();
final int chunkSize = 1 + vertices.length / 64;
final int nWorkers = vertices.length / chunkSize + 1;
final AtomicInteger countDown = new AtomicInteger(1 + nWorkers);
if (!enableDeterministicExecution) {
for(ChiVertex<VertexDataType, EdgeDataType> vertex : vertices) {
if (vertex != null) vertex.parallelSafe = true;
}
}
/* Parallel updates. One thread for non-parallel safe updates, others
updated in parallel. This guarantees deterministic execution. */
/* Non-safe updates */
parallelExecutor.submit(new Runnable() {
public void run() {
int thrupdates = 0;
GraphChiContext threadContext = chiContext.clone(0);
try {
for(ChiVertex<VertexDataType, EdgeDataType> vertex : vertices) {
if (vertex != null && !vertex.parallelSafe) {
thrupdates++;
program.update(vertex, threadContext);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
int pending = countDown.decrementAndGet();
synchronized (termlock) {
nupdates += thrupdates;
if (pending == 0) {
termlock.notifyAll();;
}
}
}
}
});
/* Parallel updates */
for(int thrId = 0; thrId < nWorkers; thrId++) {
final int myId = thrId;
final int chunkStart = myId * chunkSize;
final int chunkEnd = chunkStart + chunkSize;
parallelExecutor.submit(new Runnable() {
public void run() {
int thrupdates = 0;
GraphChiContext threadContext = chiContext.clone(1 + myId);
try {
int end = chunkEnd;
if (end > vertices.length) end = vertices.length;
for(int i = chunkStart; i < end; i++) {
ChiVertex<VertexDataType, EdgeDataType> vertex = vertices[i];
if (vertex != null && vertex.parallelSafe) {
thrupdates++;
program.update(vertex, threadContext);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
int pending = countDown.decrementAndGet();
synchronized (termlock) {
nupdates += thrupdates;
if (pending == 0) {
termlock.notifyAll();
}
}
}
}
});
}
synchronized (termlock) {
while(countDown.get() > 0) {
try {
termlock.wait(1500);
} catch (InterruptedException e) {
// What to do?
e.printStackTrace();
}
if (countDown.get() > 0) logger.info("Waiting for execution to finish: countDown:" + countDown.get());
}
}
}
_timer.stop();
}