This commit is contained in:
Garry Boyer
2007-05-20 23:45:40 +00:00
parent afeb6272c7
commit 0cec193f2d
3 changed files with 229 additions and 109 deletions
+165 -107
View File
@@ -12,14 +12,25 @@ class DualTreeDepthFirst {
};
private:
/*
KdTreeMidpointBuilder<typename GNP::QPointInfo, typename GNP::QNode,
typename GNP::Param> q_tree_;
KdTreeMidpointBuilder<typename GNP::RPointInfo, typename GNP::RNode,
typename GNP::Param> r_tree_;
*/
typename GNP::Param param_;
typename GNP::GlobalResult global_result_;
ArrayList<typename GNP::QResult> q_results_;
ArrayList<QMutableInfo> q_mutables_;
CacheArray<typename GNP::Point> q_points_;
CacheArray<typename GNP::QPointInfo> q_point_infos_;
CacheArray<typename GNP::QNode> q_nodes_;
CacheArray<typename GNP::QResult> q_results_;
CacheArray<QMutableInfo> q_mutables_;
CacheArray<typename GNP::Point> r_points_;
CacheArray<typename GNP::RPointInfo> r_point_infos_;
CacheArray<typename GNP::RNode> r_nodes_;
bool do_naive_;
datanode *datanode_;
uint64 n_naive_;
@@ -40,15 +51,46 @@ class DualTreeDepthFirst {
const typename GNP::QMassResult& exclusive_unvisited,
QMutableInfo *q_node_mut);
void PushDown_(index_t q_node_i);
private:
typename GNP::QNode *qnode_(index_t i) {
return &q_tree_.nodes()[i];
}
const typename GNP::RNode *rnode_(index_t i) {
return &r_tree_.nodes()[i];
}
};
template<typename PointInfo, typename Node, typename Param>
class LocalTreeManager {
private:
SmallCache point_cache;
SmallCache point_info_cache;
SmallCache node_cache;
public:
TreeManager();
~TreeManager();
void BuildTree(struct datanode *datanode,
const Param& param,
CacheArray<Vector> *points_out,
CacheArray<PointInfo> *point_infos_out,
CacheArray<Node> *nodes_out) {
const char *fname = fx_param_str_req(datanode, "");
Matrix matrix;
data::Load(fname, &matrix);
Vector first_data;
matrix.MakeColumnVector(0, &first_data);
PointInfo blank_info; // WALDO
BlockActionHandler *point_handler =
new CacheArrayBlockActionHandler<Vector>(first_data);
KdTreeMidpointBuilder<PointInfo, Node, Param> tree_builder;
tree_builder.InitBuild(
fx_submodule(datanode, "tree", "tree"),
&param,
points_out,
point_infos_out,
nodes_out);
}
}
template<typename GNP>
void DualTreeDepthFirst<GNP>::Init(datanode *datanode) {
datanode_ = datanode;
@@ -158,7 +200,7 @@ void DualTreeDepthFirst<GNP>::Begin() {
template<typename GNP>
void DualTreeDepthFirst<GNP>::PushDown_(index_t q_node_i) {
typename GNP::QNode *q_node = q_nodes_.StartWrite(q_node_i);
const typename GNP::QNode *q_node = q_nodes_.StartRead(q_node_i);
QMutableInfo *q_node_mut = q_mutables_.StartWrite(q_node_i);
if (q_node->is_leaf()) {
@@ -187,7 +229,7 @@ void DualTreeDepthFirst<GNP>::PushDown_(index_t q_node_i) {
}
}
q_nodes_.StopWrite(q_node_i);
q_nodes_.StopRead(q_node_i);
q_mutables_.StopWrite(q_node_i);
}
@@ -195,9 +237,9 @@ template<typename GNP>
void DualTreeDepthFirst<GNP>::Pair_(index_t q_node_i, index_t r_node_i,
const typename GNP::Delta& delta,
const typename GNP::QMassResult& exclusive_unvisited) {
typename GNP::QNode *q_node = qnode_(q_node_i);
const typename GNP::RNode *r_node = rnode_(r_node_i);
QMutableInfo *q_node_mut = &q_mutables_[q_node_i];
const typename GNP::RNode *r_node = r_nodes_.StartRead(r_node_i);
const typename GNP::QNode *q_node = q_nodes_.StartRead(q_node_i);
QMutableInfo *q_node_mut = q_mutables_.StartWrite(q_node_i);
DEBUG_MSG(1.0, "Checking (%d,%d) x (%d,%d)",
q_node->begin(), q_node->end(),
@@ -214,99 +256,103 @@ void DualTreeDepthFirst<GNP>::Pair_(index_t q_node_i, index_t r_node_i,
param_, *q_node, mu, global_result_, &q_node_mut->postponed)) {
q_node_mut->mass_result.ApplyDelta(param_, delta);
DEBUG_MSG(1.0, "Termination prune");
return;
}
if (!GNP::Algorithm::ConsiderPairExtrinsic(
} else if (!GNP::Algorithm::ConsiderPairExtrinsic(
param_, *q_node, *r_node, delta, mu, global_result_,
&q_node_mut->postponed)) {
DEBUG_MSG(1.0, "Extrinsic prune");
return;
}
/* end prune checks */
global_result_.UndoDelta(param_, delta);
if (q_node->is_leaf() && r_node->is_leaf()) {
DEBUG_MSG(1.0, "Base case");
BaseCase_(q_node, r_node, exclusive_unvisited, q_node_mut);
} else if (r_node->is_leaf()
|| (q_node->count() >= r_node->count() && !q_node->is_leaf())) {
DEBUG_MSG(1.0, "Splitting Q");
// Phase 2: Explore children, and reincorporate their results.
q_node_mut->mass_result.StartReaccumulate(param_, *q_node);
for (index_t k = 0; k < 2; k++) {
typename GNP::Delta child_delta;
index_t q_child_i = q_node->child(k);
typename GNP::QNode *q_child = qnode_(q_child_i);
QMutableInfo *q_child_mut = &q_mutables_[q_child_i];
q_child_mut->postponed.ApplyPostponed(
param_, q_node_mut->postponed);
child_delta.Init(param_);
if (GNP::Algorithm::ConsiderPairIntrinsic(
param_, *q_child, *r_node, &child_delta,
&global_result_, &q_child_mut->postponed)) {
Pair_(q_child_i, r_node_i, delta, exclusive_unvisited);
}
// We must VERY carefully apply both the horizontal and vertical join
// operators here for postponed results.
typename GNP::QMassResult tmp_result(q_child_mut->mass_result);
tmp_result.ApplyPostponed(param_, q_child_mut->postponed, *q_child);
q_node_mut->mass_result.Accumulate(param_, tmp_result, q_node->count());
}
q_node_mut->mass_result.FinishReaccumulate(param_, *q_node);
q_node_mut->postponed.Reset(param_);
} else {
DEBUG_MSG(1.0, "Splitting R");
index_t r_child1_i = r_node->child(0);
index_t r_child2_i = r_node->child(1);
const typename GNP::RNode *r_child1 = rnode_(r_child1_i);
const typename GNP::RNode *r_child2 = rnode_(r_child2_i);
double r_child1_h = GNP::Algorithm::Heuristic(
param_, *q_node, *rnode_(r_child1_i));
double r_child2_h = GNP::Algorithm::Heuristic(
param_, *q_node, *rnode_(r_child2_i));
global_result_.UndoDelta(param_, delta);
if (unlikely(r_child2_h < r_child1_h)) {
const typename GNP::RNode *r_child_t = r_child1;
r_child1 = r_child2;
r_child2 = r_child_t;
index_t r_child_t_i = r_child1_i;
r_child1_i = r_child2_i;
r_child2_i = r_child_t_i;
}
if (q_node->is_leaf() && r_node->is_leaf()) {
DEBUG_MSG(1.0, "Base case");
BaseCase_(q_node, r_node, exclusive_unvisited, q_node_mut);
} else if (r_node->is_leaf()
|| (q_node->count() >= r_node->count() && !q_node->is_leaf())) {
DEBUG_MSG(1.0, "Splitting Q");
// Phase 2: Explore children, and reincorporate their results.
q_node_mut->mass_result.StartReaccumulate(param_, *q_node);
typename GNP::Delta delta1;
typename GNP::Delta delta2;
for (index_t k = 0; k < 2; k++) {
typename GNP::Delta child_delta;
index_t q_child_i = q_node->child(k);
const typename GNP::QNode *q_child = q_nodes_.StartRead(q_child_i);
QMutableInfo *q_child_mut = q_mutables_.StartWrite(q_child_i);
q_child_mut->postponed.ApplyPostponed(
param_, q_node_mut->postponed);
child_delta.Init(param_);
delta1.Init(param_);
delta2.Init(param_);
if (GNP::Algorithm::ConsiderPairIntrinsic(
param_, *q_child, *r_node, &child_delta,
&global_result_, &q_child_mut->postponed)) {
Pair_(q_child_i, r_node_i, delta, exclusive_unvisited);
}
bool do_r2 = GNP::Algorithm::ConsiderPairIntrinsic(
param_, *q_node, *r_child2, &delta2,
&global_result_, &q_node_mut->postponed);
if (GNP::Algorithm::ConsiderPairIntrinsic(
param_, *q_node, *r_child1, &delta1,
&global_result_, &q_node_mut->postponed)) {
typename GNP::QMassResult exclusive_unvisited_for_r1(
exclusive_unvisited);
if (do_r2) {
exclusive_unvisited_for_r1.ApplyDelta(param_, delta2);
// We must VERY carefully apply both the horizontal and vertical join
// operators here for postponed results.
typename GNP::QMassResult tmp_result(q_child_mut->mass_result);
tmp_result.ApplyPostponed(param_, q_child_mut->postponed, *q_child);
q_node_mut->mass_result.Accumulate(param_, tmp_result, q_node->count());
q_mutables_.StopWrite(q_child_i);
q_nodes_.StopRead(q_child_i);
}
Pair_(q_node_i, r_child1_i, delta1, exclusive_unvisited_for_r1);
}
if (do_r2) {
Pair_(q_node_i, r_child2_i, delta2, exclusive_unvisited);
q_node_mut->mass_result.FinishReaccumulate(param_, *q_node);
q_node_mut->postponed.Reset(param_);
} else {
DEBUG_MSG(1.0, "Splitting R");
index_t r_child1_i = r_node->child(0);
index_t r_child2_i = r_node->child(1);
const typename GNP::RNode *r_child1 = r_nodes_.StartRead(r_child1_i);
const typename GNP::RNode *r_child2 = r_nodes_.StartRead(r_child2_i);
double r_child1_h = GNP::Algorithm::Heuristic(
param_, *q_node, *rnode_(r_child1_i));
double r_child2_h = GNP::Algorithm::Heuristic(
param_, *q_node, *rnode_(r_child2_i));
if (unlikely(r_child2_h < r_child1_h)) {
const typename GNP::RNode *r_child_t = r_child1;
r_child1 = r_child2;
r_child2 = r_child_t;
index_t r_child_t_i = r_child1_i;
r_child1_i = r_child2_i;
r_child2_i = r_child_t_i;
}
typename GNP::Delta delta1;
typename GNP::Delta delta2;
delta1.Init(param_);
delta2.Init(param_);
bool do_r2 = GNP::Algorithm::ConsiderPairIntrinsic(
param_, *q_node, *r_child2, &delta2,
&global_result_, &q_node_mut->postponed);
if (GNP::Algorithm::ConsiderPairIntrinsic(
param_, *q_node, *r_child1, &delta1,
&global_result_, &q_node_mut->postponed)) {
typename GNP::QMassResult exclusive_unvisited_for_r1(
exclusive_unvisited);
if (do_r2) {
exclusive_unvisited_for_r1.ApplyDelta(param_, delta2);
}
Pair_(q_node_i, r_child1_i, delta1, exclusive_unvisited_for_r1);
}
if (do_r2) {
Pair_(q_node_i, r_child2_i, delta2, exclusive_unvisited);
}
r_nodes_.StopRead(r_child1_i);
r_nodes_.StopRead(r_child2_i);
}
}
r_nodes_.StopRead(r_node_i);
q_nodes_.StopRead(q_node_i);
q_mutables_.StopWrite(q_node_i);
}
template<typename GNP>
@@ -316,9 +362,16 @@ void DualTreeDepthFirst<GNP>::BaseCase_(
const typename GNP::QMassResult& exclusive_unvisited,
QMutableInfo *q_node_mut) {
typename GNP::PairVisitor visitor;
const typename GNP::Point *r_points[r_node->count()];
const typename GNP::RPointInfo *r_infos[r_node->count()];
for (index_t r_i_rel = 0; r_i_rel < r_node->count(); ++r_i_rel) {
r_points[r_i_rel] = r_points_.StartRead(r_i_rel + r_node->begin());
r_infos[r_i_rel] = r_point_infos_.StartRead(r_i_rel + r_node->begin());
}
DEBUG_ONLY(n_pre_naive_ += q_node->count() * r_node->count());
visitor.Init(param_);
q_node_mut->mass_result.StartReaccumulate(param_, *q_node);
@@ -326,22 +379,19 @@ void DualTreeDepthFirst<GNP>::BaseCase_(
int(q_node - qnode_(0)), q_node->begin(), q_node->count());
for (index_t q_i = q_node->begin(); q_i < q_node->end(); ++q_i) {
typename GNP::Point *q_point = &q_tree_.points()[q_i];
typename GNP::QPointInfo *q_info = &q_tree_.point_info()[q_i];
typename GNP::QResult *q_result = &q_results_[q_i];
const typename GNP::Point *q_point = q_points_.StartRead(q_i);
const typename GNP::QPointInfo *q_info = q_point_infos_.StopRead(q_i);
typename GNP::QResult *q_result = q_results_.StartWrite(q_i);
q_result->ApplyPostponed(param_, q_node_mut->postponed, *q_point);
if (visitor.StartVisitingQueryPoint(param_, *q_point, *q_info, *r_node,
exclusive_unvisited, q_result, &global_result_)) {
index_t r_end = r_node->end();
for (index_t r_i = r_node->begin(); r_i < r_end; ++r_i) {
typename GNP::Point *r_point = &r_tree_.points()[r_i];
typename GNP::RPointInfo *r_info = &r_tree_.point_info()[r_i];
index_t r_count = r_node->count();
for (index_t r_i_rel = 0; r_i_rel < r_count; ++r_i_rel) {
visitor.VisitPair(param_, *q_point, *q_info, q_i,
*r_point, *r_info, r_i);
*r_point, *r_info, r_i_rel + r_node->begin());
}
visitor.FinishVisitingQueryPoint(param_, *q_point, *q_info, *r_node,
@@ -351,6 +401,15 @@ void DualTreeDepthFirst<GNP>::BaseCase_(
}
q_node_mut->mass_result.Accumulate(param_, *q_result);
q_points_.StopRead(q_i);
q_point_infos_.StopRead(q_i);
q_results_.StartRead(q_i);
}
for (index_t r_i_rel = 0; r_i_rel < r_node->count(); ++r_i_rel) {
r_points_.StopRead(r_i_rel + r_node->begin());
r_point_infos_.StopRead(r_i_rel + r_node->begin());
}
q_node_mut->mass_result.FinishReaccumulate(param_, *q_node);
@@ -358,4 +417,3 @@ void DualTreeDepthFirst<GNP>::BaseCase_(
}
#endif
+2 -2
View File
@@ -44,12 +44,12 @@ class KdTreeMidpointBuilder {
const Param* param_in_,
CacheArray<Vector> *points_in,
CacheArray<PointInfo> *point_infos_in,
CacheArray<Node> *nodes_inout) {
CacheArray<Node> *nodes_out) {
param_ = param_in_;
points_.Init(points_in, BlockDevice::MODIFY);
point_infos_.Init(nodes_, BlockDevice::MODIFY);
nodes_.Init(nodes_inout_, BlockDevice::CREATE);
nodes_.Init(nodes_out_, BlockDevice::CREATE);
allocator_.Init(&nodes_);
const Vector *first_point = points_.StartRead(points_.begin_index());
+62
View File
@@ -0,0 +1,62 @@
template<typename PointInfo, typename Node, typename Param>
class LocalTreeManager {
private:
SmallCache point_cache;
SmallCache point_info_cache;
SmallCache node_cache;
public:
TreeManager();
~TreeManager();
void BuildTree(struct datanode *datanode,
const Param& param,
CacheArray<Vector> *points_out,
CacheArray<PointInfo> *point_infos_out,
CacheArray<Node> *nodes_out) {
const char *fname = fx_param_str_req(datanode, "");
Matrix matrix;
data::Load(fname, &matrix);
Vector first_data;
matrix.MakeColumnVector(0, &first_data);
PointInfo blank_info; // WALDO
BlockActionHandler *point_handler =
new CacheArrayBlockActionHandler<Vector>(first_data);
KdTreeMidpointBuilder<PointInfo, Node, Param> tree_builder;
tree_builder.InitBuild(
fx_submodule(datanode, "tree", "tree"),
&param,
points_out,
point_infos_out,
nodes_out);
}
}
outline
template<typename GNP, typename Solverk>
class DualTreeRunner {
private:
LocalTreeManager q_;
LocalTreeManager r_;
SmallCache WALDO;
public:
void InitRun(struct datanode *datanode) {
param_.Init(fx_submodule(datanode, "param"));
}
};
int main(void) {
}