| 145 | } |
| 146 | |
| 147 | void BuddyAllocator::Free(void* p) { |
| 148 | // Point back to metadata |
| 149 | auto block = static_cast<MemoryBlock*>(p)->Metadata(); |
| 150 | #ifdef PADDLE_WITH_CUSTOM_DEVICE |
| 151 | if (use_custom_device_) { |
| 152 | block = static_cast<MemoryBlock*>(p); |
| 153 | } |
| 154 | #endif |
| 155 | // Acquire the allocator lock |
| 156 | std::lock_guard<std::mutex> lock(mutex_); |
| 157 | |
| 158 | VLOG(10) << "Free from address " << block; |
| 159 | |
| 160 | auto* desc = cache_.LoadDesc(block); |
| 161 | if (desc->get_type() == MemoryBlock::HUGE_CHUNK) { |
| 162 | VLOG(10) << "Free directly from system allocator"; |
| 163 | system_allocator_->Free(block, desc->get_total_size(), desc->get_index()); |
| 164 | |
| 165 | // Invalidate GPU allocation from cache |
| 166 | cache_.Invalidate(block); |
| 167 | |
| 168 | return; |
| 169 | } |
| 170 | |
| 171 | block->MarkAsFree(&cache_); |
| 172 | |
| 173 | total_used_ -= desc->get_total_size(); |
| 174 | total_free_ += desc->get_total_size(); |
| 175 | |
| 176 | // Trying to merge the right buddy |
| 177 | MemoryBlock* right_buddy = block->GetRightBuddy(&cache_); |
| 178 | if (right_buddy) { |
| 179 | VLOG(10) << "Merging this block " << block << " with its right buddy " |
| 180 | << right_buddy; |
| 181 | |
| 182 | auto rb_desc = cache_.LoadDesc(right_buddy); |
| 183 | if (rb_desc->get_type() == MemoryBlock::FREE_CHUNK) { |
| 184 | // Take away right buddy from pool |
| 185 | pool_.erase(IndexSizeAddress( |
| 186 | rb_desc->get_index(), rb_desc->get_total_size(), right_buddy)); |
| 187 | |
| 188 | // merge its right buddy to the block |
| 189 | block->Merge(&cache_, right_buddy); |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | // Trying to merge the left buddy |
| 194 | MemoryBlock* left_buddy = block->GetLeftBuddy(&cache_); |
| 195 | if (left_buddy) { |
| 196 | VLOG(10) << "Merging this block " << block << " with its left buddy " |
| 197 | << left_buddy; |
| 198 | |
| 199 | // auto left_buddy = block->left_buddy(cache_); |
| 200 | auto* lb_desc = cache_.LoadDesc(left_buddy); |
| 201 | if (lb_desc->get_type() == MemoryBlock::FREE_CHUNK) { |
| 202 | // Take away right buddy from pool |
| 203 | pool_.erase(IndexSizeAddress( |
| 204 | lb_desc->get_index(), lb_desc->get_total_size(), left_buddy)); |
no test coverage detected