Skip to content

Commit 49e0e68

Browse files
committed
Merge remote-tracking branches 'upstream/optimize_ndmatrix', 'upstream/fix_rr_reader', 'upstream/refactor_heap2' and 'upstream/fix_log_type' into master+wip
5 parents 0a9cb27 + 5a064ff + f09069e + 337a46c + fb3da65 commit 49e0e68

File tree

7 files changed

+602
-376
lines changed

7 files changed

+602
-376
lines changed

libs/libvtrutil/src/vtr_ndmatrix.h

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,21 @@ class NdMatrixProxy {
2828
// idim: The dimension associated with this proxy
2929
// dim_stride: The stride of this dimension (i.e. how many element in memory between indicies of this dimension)
3030
// start: Pointer to the start of the sub-matrix this proxy represents
31-
NdMatrixProxy<T, N>(const size_t* dim_sizes, size_t idim, size_t dim_stride, T* start)
31+
NdMatrixProxy<T, N>(const size_t* dim_sizes, const size_t* dim_strides, T* start)
3232
: dim_sizes_(dim_sizes)
33-
, idim_(idim)
34-
, dim_stride_(dim_stride)
33+
, dim_strides_(dim_strides)
3534
, start_(start) {}
3635

3736
const NdMatrixProxy<T, N - 1> operator[](size_t index) const {
3837
VTR_ASSERT_SAFE_MSG(index >= 0, "Index out of range (below dimension minimum)");
39-
VTR_ASSERT_SAFE_MSG(index < dim_sizes_[idim_], "Index out of range (above dimension maximum)");
40-
41-
size_t next_dim_size = dim_sizes_[idim_ + 1];
42-
VTR_ASSERT_SAFE_MSG(next_dim_size > 0, "Can not index into zero-sized dimension");
43-
44-
//Determine the stride of the next dimension
45-
size_t next_dim_stride = dim_stride_ / next_dim_size;
38+
VTR_ASSERT_SAFE_MSG(index < dim_sizes_[0], "Index out of range (above dimension maximum)");
39+
VTR_ASSERT_SAFE_MSG(dim_sizes_[1] > 0, "Can not index into zero-sized dimension");
4640

4741
//Strip off one dimension
48-
return NdMatrixProxy<T, N - 1>(dim_sizes_, //Pass the dimension information
49-
idim_ + 1, //Pass the next dimension
50-
next_dim_stride, //Pass the stride for the next dimension
51-
start_ + dim_stride_ * index); //Advance to index in this dimension
42+
return NdMatrixProxy<T, N - 1>(
43+
dim_sizes_ + 1, //Pass the dimension information
44+
dim_strides_ + 1, //Pass the stride for the next dimension
45+
start_ + dim_strides_[0] * index); //Advance to index in this dimension
5246
}
5347

5448
NdMatrixProxy<T, N - 1> operator[](size_t index) {
@@ -58,25 +52,23 @@ class NdMatrixProxy {
5852

5953
private:
6054
const size_t* dim_sizes_;
61-
const size_t idim_;
62-
const size_t dim_stride_;
55+
const size_t* dim_strides_;
6356
T* start_;
6457
};
6558

6659
//Base case: 1-dimensional array
6760
template<typename T>
6861
class NdMatrixProxy<T, 1> {
6962
public:
70-
NdMatrixProxy<T, 1>(const size_t* dim_sizes, size_t idim, size_t dim_stride, T* start)
63+
NdMatrixProxy<T, 1>(const size_t* dim_sizes, const size_t* dim_stride, T* start)
7164
: dim_sizes_(dim_sizes)
72-
, idim_(idim)
73-
, dim_stride_(dim_stride)
65+
, dim_strides_(dim_stride)
7466
, start_(start) {}
7567

7668
const T& operator[](size_t index) const {
77-
VTR_ASSERT_SAFE_MSG(dim_stride_ == 1, "Final dimension must have stride 1");
69+
VTR_ASSERT_SAFE_MSG(dim_strides_[0] == 1, "Final dimension must have stride 1");
7870
VTR_ASSERT_SAFE_MSG(index >= 0, "Index out of range (below dimension minimum)");
79-
VTR_ASSERT_SAFE_MSG(index < dim_sizes_[idim_], "Index out of range (above dimension maximum)");
71+
VTR_ASSERT_SAFE_MSG(index < dim_sizes_[0], "Index out of range (above dimension maximum)");
8072

8173
//Base case
8274
return start_[index];
@@ -103,8 +95,7 @@ class NdMatrixProxy<T, 1> {
10395

10496
private:
10597
const size_t* dim_sizes_;
106-
const size_t idim_;
107-
const size_t dim_stride_;
98+
const size_t* dim_strides_;
10899
T* start_;
109100
};
110101

@@ -207,12 +198,21 @@ class NdMatrixBase {
207198
size_ = calc_size();
208199
alloc();
209200
fill(value);
201+
if (size_ > 0) {
202+
dim_strides_[0] = size_ / dim_sizes_[0];
203+
for (size_t dim = 1; dim < N; ++dim) {
204+
dim_strides_[dim] = dim_strides_[dim - 1] / dim_sizes_[dim];
205+
}
206+
} else {
207+
dim_strides_.fill(0);
208+
}
210209
}
211210

212211
//Reset the matrix to size zero
213212
void clear() {
214213
data_.reset(nullptr);
215214
dim_sizes_.fill(0);
215+
dim_strides_.fill(0);
216216
size_ = 0;
217217
}
218218

@@ -242,6 +242,7 @@ class NdMatrixBase {
242242
using std::swap;
243243
swap(m1.size_, m2.size_);
244244
swap(m1.dim_sizes_, m2.dim_sizes_);
245+
swap(m1.dim_strides_, m2.dim_strides_);
245246
swap(m1.data_, m2.data_);
246247
}
247248

@@ -265,6 +266,7 @@ class NdMatrixBase {
265266
protected:
266267
size_t size_ = 0;
267268
std::array<size_t, N> dim_sizes_;
269+
std::array<size_t, N> dim_strides_;
268270
std::unique_ptr<T[]> data_ = nullptr;
269271
};
270272

@@ -316,17 +318,11 @@ class NdMatrix : public NdMatrixBase<T, N> {
316318
VTR_ASSERT_SAFE_MSG(index >= 0, "Index out of range (below dimension minimum)");
317319
VTR_ASSERT_SAFE_MSG(index < this->dim_sizes_[0], "Index out of range (above dimension maximum)");
318320

319-
//Calculate the stride for the current dimension
320-
size_t dim_stride = this->size() / this->dim_size(0);
321-
322-
//Calculate the stride for the next dimension
323-
size_t next_dim_stride = dim_stride / this->dim_size(1);
324-
325321
//Peel off the first dimension
326-
return NdMatrixProxy<T, N - 1>(this->dim_sizes_.data(), //Pass the dimension information
327-
1, //Pass the next dimension
328-
next_dim_stride, //Pass the stride for the next dimension
329-
this->data_.get() + dim_stride * index); //Advance to index in this dimension
322+
return NdMatrixProxy<T, N - 1>(
323+
this->dim_sizes_.data() + 1, //Pass the dimension information
324+
this->dim_strides_.data() + 1, //Pass the stride for the next dimension
325+
this->data_.get() + this->dim_strides_[0] * index); //Advance to index in this dimension
330326
}
331327

332328
//Access an element

vpr/src/place/place.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ std::unique_ptr<FILE, decltype(&vtr::fclose)> f_move_stats_file(nullptr, vtr::fc
278278
t_pl_loc to = affected_blocks.moved_blocks[0].new_loc; \
279279
ClusterBlockId b_to = place_ctx.grid_blocks[to.x][to.y].blocks[to.z]; \
280280
\
281-
t_physical_tile_type_ptr from_type = cluster_ctx.clb_nlist.block_type(b_from); \
282-
t_physical_tile_type_ptr to_type = nullptr; \
281+
t_logical_block_type_ptr from_type = cluster_ctx.clb_nlist.block_type(b_from); \
282+
t_logical_block_type_ptr to_type = nullptr; \
283283
if (b_to) { \
284284
to_type = cluster_ctx.clb_nlist.block_type(b_to); \
285285
} \

vpr/src/route/bucket.cpp

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#include "bucket.h"
2+
3+
std::vector<t_heap*> BucketItems::heap_items_;
4+
size_t BucketItems::alloced_items_ = 0;
5+
int BucketItems::num_heap_allocated_ = 0;
6+
t_heap* BucketItems::heap_free_head_ = nullptr;
7+
vtr::t_chunk BucketItems::heap_ch_;
8+
9+
void Bucket::init(const DeviceGrid& grid) {
10+
vtr::free(heap_);
11+
heap_ = nullptr;
12+
13+
heap_size_ = (grid.width() - 1) * (grid.height() - 1);
14+
heap_ = (t_heap**)vtr::malloc(heap_size_ * sizeof(t_heap*));
15+
memset(heap_, 0, heap_size_ * sizeof(t_heap*));
16+
17+
heap_head_ = std::numeric_limits<size_t>::max();
18+
heap_tail_ = 0;
19+
20+
conv_factor_ = kDefaultConvFactor;
21+
22+
min_cost_ = std::numeric_limits<float>::max();
23+
max_cost_ = std::numeric_limits<float>::min();
24+
}
25+
26+
void Bucket::free() {
27+
vtr::free(heap_);
28+
heap_ = nullptr;
29+
}
30+
31+
void Bucket::expand(size_t required_number_of_buckets) {
32+
auto old_size = heap_size_;
33+
heap_size_ = required_number_of_buckets * 2;
34+
35+
heap_ = (t_heap**)vtr::realloc((void*)(heap_),
36+
heap_size_ * sizeof(t_heap*));
37+
std::fill(heap_ + old_size, heap_ + heap_size_, nullptr);
38+
}
39+
40+
void Bucket::verify() {
41+
for (size_t bucket = heap_head_; bucket <= heap_tail_; ++bucket) {
42+
for (t_heap* data = heap_[bucket]; data != nullptr;
43+
data = data->next_bucket) {
44+
VTR_ASSERT(data->cost > 0 && ((size_t)cost_to_int(data->cost)) == bucket);
45+
}
46+
}
47+
}
48+
49+
size_t Bucket::seed_ = 1231;
50+
t_heap** Bucket::heap_ = nullptr;
51+
size_t Bucket::heap_size_ = 0;
52+
size_t Bucket::heap_head_ = std::numeric_limits<size_t>::max();
53+
size_t Bucket::heap_tail_ = 0;
54+
float Bucket::min_cost_ = 0.f;
55+
float Bucket::max_cost_ = 0.f;
56+
float Bucket::conv_factor_ = 0.f;
57+
58+
void Bucket::clear() {
59+
if (heap_head_ != std::numeric_limits<size_t>::max()) {
60+
std::fill(heap_ + heap_head_, heap_ + heap_tail_ + 1, nullptr);
61+
}
62+
heap_head_ = std::numeric_limits<size_t>::max();
63+
heap_tail_ = 0;
64+
}
65+
66+
void Bucket::check_scaling() {
67+
float min_cost = min_cost_;
68+
float max_cost = max_cost_;
69+
VTR_ASSERT(max_cost != std::numeric_limits<float>::min());
70+
if (min_cost == std::numeric_limits<float>::max()) {
71+
min_cost = max_cost;
72+
}
73+
auto min_bucket = cost_to_int(min_cost);
74+
auto max_bucket = cost_to_int(max_cost);
75+
76+
if (min_bucket < 0 || max_bucket < 0 || max_bucket > 1000000) {
77+
// If min and max are close to each other, assume 3 orders of
78+
// magnitude between min and max.
79+
//
80+
// If min and max are at least 3 orders of magnitude apart, scale
81+
// soley based on max cost.
82+
conv_factor_ = 50000.f / max_cost_ / std::max(1.f, 1000.f / (max_cost_ / min_cost_));
83+
84+
VTR_ASSERT(cost_to_int(min_cost_) >= 0);
85+
VTR_ASSERT(cost_to_int(max_cost_) >= 0);
86+
VTR_ASSERT(cost_to_int(max_cost_) < 1000000);
87+
88+
// Reheap after adjusting scaling.
89+
if (heap_head_ != std::numeric_limits<size_t>::max()) {
90+
std::vector<t_heap*> reheap;
91+
for (size_t bucket = heap_head_; bucket <= heap_tail_; ++bucket) {
92+
for (t_heap* item = heap_[bucket]; item != nullptr; item = item->next_bucket) {
93+
reheap.push_back(item);
94+
}
95+
}
96+
97+
std::fill(heap_ + heap_head_, heap_ + heap_tail_ + 1, nullptr);
98+
heap_head_ = std::numeric_limits<size_t>::max();
99+
heap_tail_ = 0;
100+
101+
for (t_heap* item : reheap) {
102+
push(item);
103+
}
104+
}
105+
}
106+
}
107+
108+
void Bucket::push(t_heap* hptr) {
109+
float cost = hptr->cost;
110+
if (!std::isfinite(cost)) {
111+
return;
112+
}
113+
114+
bool check_scale = false;
115+
// Exclude 0 cost from min_cost to provide useful scaling factor.
116+
if (cost < min_cost_ && cost > 0) {
117+
min_cost_ = cost;
118+
check_scale = true;
119+
}
120+
if (cost > max_cost_) {
121+
max_cost_ = cost;
122+
check_scale = true;
123+
}
124+
125+
if (check_scale) {
126+
check_scaling();
127+
}
128+
129+
// Which bucket should this go into?
130+
auto int_cost = cost_to_int(cost);
131+
132+
if (int_cost < 0) {
133+
VTR_LOG_WARN("Cost is negative? cost = %g, bucket = %d\n", cost, int_cost);
134+
int_cost = 0;
135+
}
136+
137+
size_t uint_cost = int_cost;
138+
139+
// Is that bucket allocated?
140+
if (uint_cost >= heap_size_) {
141+
// Not enough buckets!
142+
expand(uint_cost);
143+
}
144+
145+
// Insert into bucket
146+
auto* prev = heap_[uint_cost];
147+
hptr->next_bucket = prev;
148+
heap_[uint_cost] = hptr;
149+
150+
if (uint_cost < heap_head_) {
151+
heap_head_ = uint_cost;
152+
}
153+
if (uint_cost > heap_tail_) {
154+
heap_tail_ = uint_cost;
155+
}
156+
}
157+
158+
t_heap* Bucket::pop() {
159+
auto heap_head = heap_head_;
160+
auto heap_tail = heap_tail_;
161+
t_heap** heap = heap_;
162+
163+
// Check empty
164+
if (heap_head == std::numeric_limits<size_t>::max()) {
165+
return nullptr;
166+
}
167+
168+
// Find first non-empty bucket
169+
170+
// Randomly remove element
171+
size_t count = fast_rand() % 4;
172+
173+
t_heap* prev = nullptr;
174+
t_heap* next = heap[heap_head];
175+
for (size_t i = 0; i < count && next->next_bucket != nullptr; ++i) {
176+
prev = next;
177+
next = prev->next_bucket;
178+
}
179+
180+
if (prev == nullptr) {
181+
heap[heap_head] = next->next_bucket;
182+
} else {
183+
prev->next_bucket = next->next_bucket;
184+
}
185+
186+
// Update first non-empty bucket if bucket is now empty
187+
if (heap[heap_head] == nullptr) {
188+
heap_head += 1;
189+
while (heap_head <= heap_tail && heap[heap_head] == nullptr) {
190+
heap_head += 1;
191+
}
192+
193+
if (heap_head > heap_tail) {
194+
heap_head = std::numeric_limits<size_t>::max();
195+
}
196+
197+
heap_head_ = heap_head;
198+
}
199+
200+
return next;
201+
}
202+
203+
void Bucket::print() {
204+
for (size_t i = heap_head_; i < heap_tail_; ++i) {
205+
if (heap_[heap_head_] != nullptr) {
206+
VTR_LOG("B:%d ", i);
207+
for (auto* item = heap_[i]; item != nullptr; item = item->next_bucket) {
208+
VTR_LOG(" %e", item->cost);
209+
}
210+
}
211+
}
212+
VTR_LOG("\n");
213+
}

0 commit comments

Comments
 (0)