我想通过在两个不同的线程上运行该方法来减少DatabaseUtil.precomputedKNNQuery方法的运行时间,并且KNNQuery是一个接口。
KNNQuery<O> knnq = DatabaseUtil.precomputedKNNQuery(database, relation, getDistanceFunction(), k);
我将LOF类的这种方法分为两个部分
Callable<KNNQuery> task1(Database database, Relation<O> relation){
DBIDs idss = relation.getDBIDs();
ArrayDBIDs aids = (ArrayDBIDs) idss;
aids = aids.slice(0, (aids.size() / 2));
aids.size();
ProxyView<O> pv = new ProxyView<>(aids, relation);
return () -> {
return DatabaseUtil.precomputedKNNQuery(database, pv,
getDistanceFunction(), k);
};
}
Callable<KNNQuery> task2(Database database, Relation<O> relation) {
DBIDs idss = relation.getDBIDs();
ArrayDBIDs aids = (ArrayDBIDs) idss;
aids = aids.slice(((aids.size() / 2) - 1), aids.size());
aids.size();
ProxyView<O> pv2 = new ProxyView<>(aids, relation);
return () -> {
return DatabaseUtil.precomputedKNNQuery(database, pv2, getDistanceFunction(), k);
};
}
然后我在LOF类的run()方法中的两个不同线程上调用了这两个任务
public OutlierResult run(Database database, Relation<O> relation) {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress("LOF", 3) : null;
DBIDs ids = relation.getDBIDs();
LOG.beginStep(stepprog, 1, "Materializing nearest-neighbor sets.");
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<KNNQuery>> callables = Arrays.asList(
task1(database, relation),
task2(database, relation));
for (Future<KNNQuery> future : executor.invokeAll(callables)) {
KNNQuery<O> knnq = future.get();
// Compute LRDs
// compute LOF_SCORE of each db object
// Build result representation
}
}
但是我遇到了这样的异常,因为forEach仅在knnq变量中提供第一个Future的输出,而不提供两个Future的组合输出。请帮我如何摆脱这种例外,并附上示例感谢?
de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection.load: 505 ms
LOF #1/3: Materializing nearest-neighbor sets.
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor.k: 4
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor.k: 4
Materializing k nearest neighbors (k=4): 21751 [100%] de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor.precomputation-time: 21470 ms
Materializing k nearest neighbors (k=4): 21750 [100%]
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor.precomputation-time: 22355 ms
LOF #2/3: Computing Local Reachability Densities (LRD).
Task failed
de.lmu.ifi.dbs.elki.database.datastore.ObjectNotFoundException: Object
21751 was not found in the database.
at de.lmu.ifi.dbs.elki.database.datastore.memory.ArrayStore.get(ArrayStore.java:69)
at de.lmu.ifi.dbs.elki.index.preprocessed.knn.AbstractMaterializeKNNPreprocessor.get(AbstractMaterializeKNNPreprocessor.java:118)
at de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery.getKNNForDBID(PreprocessorKNNQuery.java:84)
at de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF.computeLRD(LOF.java:292)
at de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF.computeLRDs(LOF.java:277)
at de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF.run(LOF.java:244)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm.run(AbstractAlgorithm.java:89)
at de.lmu.ifi.dbs.elki.workflow.AlgorithmStep.runAlgorithms(AlgorithmStep.java:100)
at de.lmu.ifi.dbs.elki.KDDTask.run(KDDTask.java:109)
at de.lmu.ifi.dbs.elki.application.KDDCLIApplication.run(KDDCLIApplication.java:58)
at [...]
答案 0 :(得分:0)
如果以此方式拆分数据集,则一个分区的邻居将看不到其他分区的邻居。
您似乎想并行化LOF。为什么不只使用现有的并行LOF?
您可以研究源代码,以了解如何将其与类似map-reduce的框架并行进行:
或者-更接近您现在正在执行的操作-您可以执行两个分区,在两个分区上运行LOF,然后通过复制“合并”两个LOF结果。在运行LOF之前加入kNN结果没有任何好处,因为它们将保持独立-分区A中的一个对象不会像分区数据那样设置分区B中的邻居。
请注意,DatabaseUtil.precomputedKNNQuery
是许多方法中使用的功能的便捷方法。但这不是“必需”的。 ParallelLOF
版本不使用它,因为它不是并行的。
在将来的ELKI 0.8中,我希望我们将拥有可以根据需要自动设置索引(包括预先计算的索引)的基础架构;并可能带有允许并行执行此操作的标志(或不允许-对于运行时比较,单线程算法通常会产生更有意义的结果)。