You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

small_vector.h 29 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. /**
  2. * \file dnn/include/megdnn/thin/small_vector.h
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
  12. //
  13. // The LLVM Compiler Infrastructure
  14. //
  15. // This file is distributed under the University of Illinois Open Source
  16. // License. See LICENSE.TXT for details.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. //
  20. // This file defines the SmallVector class.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. /**
  24. * \file include/megdnn/thin/small_vector.h
  25. *
  26. * This file is part of MegDNN, a deep neural network run-time library
  27. * developed by Megvii.
  28. *
  29. * \brief thin megdnn function
  30. *
  31. * \copyright Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  32. */
  33. #pragma once
  34. #include "megdnn/arch.h"
  35. #include <algorithm>
  36. #include <cstdlib>
  37. #include <cstring>
  38. #include <iterator>
  39. #include <limits>
  40. #include <memory>
  41. #include <type_traits>
  42. #include "megdnn/internal/visibility_prologue.h"
  43. namespace megdnn {
  44. class SmallVectorBase {
  45. protected:
  46. void *m_begin_ptr, *m_end_ptr, *m_capacity_ptr;
  47. MEGDNN_NORETURN static void on_invalid_at(size_t idx, size_t size);
  48. protected:
  49. SmallVectorBase(void* first_elm, size_t size)
  50. : m_begin_ptr(first_elm),
  51. m_end_ptr(first_elm),
  52. m_capacity_ptr(static_cast<char*>(first_elm) + size) {}
  53. void grow_pod(void* first_elm_ptr, size_t min_sz_in_bytes, size_t type_size);
  54. public:
  55. size_t size_in_bytes() const {
  56. return size_t(static_cast<char*>(m_end_ptr) - static_cast<char*>(m_begin_ptr));
  57. }
  58. size_t capacity_in_bytes() const {
  59. return size_t(
  60. static_cast<char*>(m_capacity_ptr) - static_cast<char*>(m_begin_ptr));
  61. }
  62. bool empty() const { return m_begin_ptr == m_end_ptr; }
  63. };
  64. template <typename T, typename = void>
  65. class SmallVectorTemplateCommon : public SmallVectorBase {
  66. private:
  67. template <typename, unsigned>
  68. friend struct SmallVectorStorage;
  69. using U = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
  70. U m_first_elm;
  71. protected:
  72. SmallVectorTemplateCommon(size_t size) : SmallVectorBase(&m_first_elm, size) {}
  73. void grow_pod(size_t min_sz_in_bytes, size_t type_size) {
  74. SmallVectorBase::grow_pod(&m_first_elm, min_sz_in_bytes, type_size);
  75. }
  76. bool is_small() { return m_begin_ptr == static_cast<const void*>(&m_first_elm); }
  77. void reset_to_small() { m_begin_ptr = m_end_ptr = m_capacity_ptr = &m_first_elm; }
  78. void set_end(T* p) { m_end_ptr = p; }
  79. public:
  80. using size_type = size_t;
  81. using difference_type = std::ptrdiff_t;
  82. using value_type = T;
  83. using iterator = T*;
  84. using const_iterator = const T*;
  85. using reverse_iterator = std::reverse_iterator<iterator>;
  86. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  87. using reference = T&;
  88. using const_reference = const T&;
  89. using pointer = T*;
  90. using const_pointer = const T*;
  91. size_t capacity() const { return capacity_ptr() - begin(); }
  92. protected:
  93. iterator capacity_ptr() { return static_cast<iterator>(m_capacity_ptr); }
  94. const_iterator capacity_ptr() const {
  95. return static_cast<const_iterator>(m_capacity_ptr);
  96. }
  97. public:
  98. // forwarding iterator creation
  99. iterator begin() { return static_cast<iterator>(m_begin_ptr); }
  100. const_iterator begin() const { return static_cast<const_iterator>(m_begin_ptr); }
  101. const_iterator cbegin() const { return static_cast<const_iterator>(m_begin_ptr); }
  102. iterator end() { return static_cast<iterator>(m_end_ptr); }
  103. const_iterator end() const { return static_cast<const_iterator>(m_end_ptr); }
  104. const_iterator cend() const { return static_cast<const_iterator>(m_end_ptr); }
  105. reference at(size_type idx) {
  106. if (idx >= size()) {
  107. on_invalid_at(idx, size());
  108. }
  109. return begin()[idx];
  110. }
  111. const_reference at(size_type idx) const {
  112. if (idx >= size()) {
  113. on_invalid_at(idx, size());
  114. }
  115. return begin()[idx];
  116. }
  117. reference operator[](size_type idx) { return begin()[idx]; }
  118. const_reference operator[](size_type idx) const { return begin()[idx]; }
  119. reference front() { return begin()[0]; }
  120. const_reference front() const { return begin()[0]; }
  121. reference back() { return rbegin()[0]; }
  122. const_reference back() const { return rbegin()[0]; }
  123. // reverse iterator creation method.
  124. reverse_iterator rbegin() { return reverse_iterator(end()); }
  125. const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
  126. reverse_iterator rend() { return reverse_iterator(begin()); }
  127. const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
  128. pointer data() { return pointer(begin()); }
  129. const_pointer data() const { return const_pointer(begin()); }
  130. size_type size() const { return end() - begin(); }
  131. size_type max_size() const {
  132. return std::numeric_limits<size_type>::max() / sizeof(T);
  133. }
  134. template <typename in_iter>
  135. in_iter find(in_iter first, in_iter last, const T& value) const {
  136. while (first != last) {
  137. if (*first == value)
  138. return first;
  139. ++first;
  140. }
  141. return last;
  142. }
  143. };
  144. template <typename T, bool is_pod>
  145. class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
  146. protected:
  147. SmallVectorTemplateBase(size_t size) : SmallVectorTemplateCommon<T>(size) {}
  148. static void destroy_range(T* start, T* end) {
  149. while (start != end) {
  150. --end;
  151. end->~T();
  152. }
  153. }
  154. template <typename It1, typename It2>
  155. static void uninitialized_move(It1 first, It1 last, It2 dest) {
  156. std::uninitialized_copy(
  157. std::make_move_iterator(first), std::make_move_iterator(last), dest);
  158. }
  159. template <typename It1, typename It2>
  160. static void uninitialized_copy(It1 first, It1 last, It2 dest) {
  161. std::uninitialized_copy(first, last, dest);
  162. }
  163. void grow(size_t min_sz = 0);
  164. public:
  165. void push_back(const T& _elm) {
  166. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  167. T elm = _elm;
  168. this->grow();
  169. new (static_cast<void*>(this->end())) T(std::move(elm));
  170. } else {
  171. new (static_cast<void*>(this->end())) T(_elm);
  172. }
  173. this->set_end(this->end() + 1);
  174. }
  175. void push_back(T&& elm) {
  176. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  177. this->grow();
  178. }
  179. new (static_cast<void*>(this->end())) T(std::move(elm));
  180. this->set_end(this->end() + 1);
  181. }
  182. void pop_back() {
  183. this->set_end(this->end() - 1);
  184. this->end()->~T();
  185. }
  186. };
  187. template <typename T, bool is_pod>
  188. void SmallVectorTemplateBase<T, is_pod>::grow(size_t min_sz) {
  189. size_t cur_capacity = this->capacity();
  190. size_t cur_sz = this->size();
  191. size_t new_capacity = (cur_capacity + 2) * 2;
  192. if (new_capacity < min_sz) {
  193. new_capacity = min_sz;
  194. }
  195. T* elms = static_cast<T*>(malloc(new_capacity * sizeof(T)));
  196. this->uninitialized_move(this->begin(), this->end(), elms);
  197. this->destroy_range(this->begin(), this->end());
  198. if (!this->is_small()) {
  199. free(this->begin());
  200. }
  201. this->m_begin_ptr = elms;
  202. this->set_end(elms + cur_sz);
  203. this->m_capacity_ptr = this->begin() + new_capacity;
  204. }
  205. template <typename T>
  206. class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
  207. protected:
  208. SmallVectorTemplateBase(size_t size) : SmallVectorTemplateCommon<T>(size) {}
  209. static void destroy_range(T*, T*) {}
  210. template <typename It1, typename It2>
  211. static void uninitialized_move(It1 first, It1 last, It2 dest) {
  212. uninitialized_copy(first, last, dest);
  213. }
  214. template <typename It1, typename It2>
  215. static void uninitialized_copy(It1 first, It1 last, It2 dest) {
  216. std::uninitialized_copy(first, last, dest);
  217. }
  218. template <typename T1, typename T2>
  219. static void uninitialized_copy(
  220. T1* first, T1* last, T2* dest,
  221. typename std::enable_if<std::is_same<
  222. typename std::remove_const<T1>::type, T2>::value>::type* =
  223. nullptr) {
  224. if (first != last)
  225. memcpy(dest, first, (last - first) * sizeof(T));
  226. }
  227. void grow(size_t min_sz = 0) { this->grow_pod(min_sz * sizeof(T), sizeof(T)); }
  228. public:
  229. void push_back(const T& _elm) {
  230. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  231. T elm = _elm;
  232. this->grow();
  233. memcpy(this->end(), &elm, sizeof(T));
  234. } else {
  235. memcpy(this->end(), &_elm, sizeof(T));
  236. }
  237. this->set_end(this->end() + 1);
  238. }
  239. void pop_back() { this->set_end(this->end() - 1); }
  240. };
  241. /*!
  242. * \brief the implementation class of SmallVector
  243. *
  244. * SmallVector<T, N> can be converted to SmallVectorImpl<T> to erase N
  245. */
  246. template <typename T>
  247. class SmallVectorImpl : public SmallVectorTemplateBase<T, std::is_pod<T>::value> {
  248. using SuperClass = SmallVectorTemplateBase<T, std::is_pod<T>::value>;
  249. public:
  250. using iterator = typename SuperClass::iterator;
  251. using const_iterator = typename SuperClass::const_iterator;
  252. using size_type = typename SuperClass::size_type;
  253. protected:
  254. explicit SmallVectorImpl(unsigned n)
  255. : SmallVectorTemplateBase<T, std::is_pod<T>::value>(n * sizeof(T)) {}
  256. public:
  257. SmallVectorImpl(const SmallVectorImpl&) = delete;
  258. ~SmallVectorImpl() {
  259. this->destroy_range(this->begin(), this->end());
  260. if (!this->is_small())
  261. free(this->begin());
  262. }
  263. void clear() {
  264. this->destroy_range(this->begin(), this->end());
  265. this->m_end_ptr = this->m_begin_ptr;
  266. }
  267. void resize(size_type n) {
  268. if (n < this->size()) {
  269. this->destroy_range(this->begin() + n, this->end());
  270. this->set_end(this->begin() + n);
  271. } else if (n > this->size()) {
  272. if (this->capacity() < n)
  273. this->grow(n);
  274. for (auto it = this->end(), end = this->begin() + n; it != end; ++it)
  275. new (&*it) T();
  276. this->set_end(this->begin() + n);
  277. }
  278. }
  279. void resize(size_type n, const T& _nv) {
  280. T nv = _nv;
  281. if (n < this->size()) {
  282. this->destroy_range(this->begin() + n, this->end());
  283. this->set_end(this->begin() + n);
  284. } else if (n > this->size()) {
  285. if (this->capacity() < n)
  286. this->grow(n);
  287. std::uninitialized_fill(this->end(), this->begin() + n, nv);
  288. this->set_end(this->begin() + n);
  289. }
  290. }
  291. void reserve(size_type n) {
  292. if (this->capacity() < n) {
  293. this->grow(n);
  294. }
  295. }
  296. T pop_back_val() {
  297. T result = std::move(this->back());
  298. this->pop_back();
  299. return result;
  300. }
  301. void swap(SmallVectorImpl<T>& rhs);
  302. /// Add the specified range to the end of the SmallVector.
  303. template <
  304. typename in_iter,
  305. typename = typename std::enable_if<std::is_convertible<
  306. typename std::iterator_traits<in_iter>::iterator_category,
  307. std::input_iterator_tag>::value>::type>
  308. void append(in_iter in_start, in_iter in_end) {
  309. size_type num_inputs = std::distance(in_start, in_end);
  310. // Grow allocated space if needed.
  311. if (num_inputs > size_type(this->capacity_ptr() - this->end()))
  312. this->grow(this->size() + num_inputs);
  313. // Copy the new elements over.
  314. this->uninitialized_copy(in_start, in_end, this->end());
  315. this->set_end(this->end() + num_inputs);
  316. }
  317. /// Add the specified range to the end of the SmallVector.
  318. void append(size_type num_inputs, const T& _elm) {
  319. T elm = _elm;
  320. // Grow allocated space if needed.
  321. if (num_inputs > size_type(this->capacity_ptr() - this->end()))
  322. this->grow(this->size() + num_inputs);
  323. // Copy the new elements over.
  324. std::uninitialized_fill_n(this->end(), num_inputs, elm);
  325. this->set_end(this->end() + num_inputs);
  326. }
  327. void append(std::initializer_list<T> init_list) {
  328. append(init_list.begin(), init_list.end());
  329. }
  330. // FIXME: Consider assigning over existing elements, rather than clearing &
  331. // re-initializing them - for all assign(...) variants.
  332. void assign(size_type num_elms, const T& _elm) {
  333. T elm = _elm;
  334. clear();
  335. if (this->capacity() < num_elms)
  336. this->grow(num_elms);
  337. this->set_end(this->begin() + num_elms);
  338. std::uninitialized_fill(this->begin(), this->end(), elm);
  339. }
  340. template <
  341. typename in_iter,
  342. typename = typename std::enable_if<std::is_convertible<
  343. typename std::iterator_traits<in_iter>::iterator_category,
  344. std::input_iterator_tag>::value>::type>
  345. void assign(in_iter in_start, in_iter in_end) {
  346. clear();
  347. append(in_start, in_end);
  348. }
  349. void assign(std::initializer_list<T> init_list) {
  350. clear();
  351. append(init_list);
  352. }
  353. iterator erase(const_iterator cit) {
  354. // Just cast away constness because this is a non-const member function.
  355. iterator it = const_cast<iterator>(cit);
  356. iterator n = it;
  357. // Shift all elms down one.
  358. std::move(it + 1, this->end(), it);
  359. // Drop the last elm.
  360. this->pop_back();
  361. return (n);
  362. }
  363. iterator erase(const_iterator c_first, const_iterator c_last) {
  364. // Just cast away constness because this is a non-const member function.
  365. iterator first = const_cast<iterator>(c_first);
  366. iterator last = const_cast<iterator>(c_last);
  367. iterator n = first;
  368. // Shift all elms down.
  369. iterator it = std::move(last, this->end(), first);
  370. // Drop the last elms.
  371. this->destroy_range(it, this->end());
  372. this->set_end(it);
  373. return (n);
  374. }
  375. iterator insert(iterator it, T&& elm) {
  376. if (it == this->end()) { // Important special case for empty vector.
  377. this->push_back(std::move(elm));
  378. return this->end() - 1;
  379. }
  380. if (this->m_end_ptr >= this->m_capacity_ptr) {
  381. size_t elm_idx = it - this->begin();
  382. this->grow();
  383. it = this->begin() + elm_idx;
  384. }
  385. new (static_cast<void*>(this->end())) T(std::move(this->back()));
  386. // Push everything else over.
  387. std::move_backward(it, this->end() - 1, this->end());
  388. this->set_end(this->end() + 1);
  389. // If we just moved the element we're inserting, be sure to update
  390. // the reference.
  391. T* elm_ptr = &elm;
  392. if (it <= elm_ptr && elm_ptr < this->m_end_ptr)
  393. ++elm_ptr;
  394. *it = std::move(*elm_ptr);
  395. return it;
  396. }
  397. iterator insert(iterator it, const T& _elm) {
  398. if (it == this->end()) { // Important special case for empty vector.
  399. this->push_back(_elm);
  400. return this->end() - 1;
  401. }
  402. T elm = _elm;
  403. if (this->m_end_ptr >= this->m_capacity_ptr) {
  404. size_t elm_idx = it - this->begin();
  405. this->grow();
  406. it = this->begin() + elm_idx;
  407. }
  408. new (static_cast<void*>(this->end())) T(std::move(this->back()));
  409. // Push everything else over.
  410. std::move_backward(it, this->end() - 1, this->end());
  411. this->set_end(this->end() + 1);
  412. // If we just moved the element we're inserting, be sure to update
  413. // the reference.
  414. const T* elm_ptr = &elm;
  415. if (it <= elm_ptr && elm_ptr < this->m_end_ptr)
  416. ++elm_ptr;
  417. *it = *elm_ptr;
  418. return it;
  419. }
  420. iterator insert(iterator it, size_type num_to_insert, const T& _elm) {
  421. // Convert iterator to elm# to avoid invalidating iterator
  422. // when we reserve()
  423. size_t elm_idx = it - this->begin();
  424. if (it == this->end()) { // Important special case for empty vector.
  425. append(num_to_insert, _elm);
  426. return this->begin() + elm_idx;
  427. }
  428. T elm = _elm;
  429. // Ensure there is enough space.
  430. reserve(this->size() + num_to_insert);
  431. // Uninvalidate the iterator.
  432. it = this->begin() + elm_idx;
  433. // If there are more elements between the insertion point and
  434. // the end of the range than there are being inserted,
  435. // we can use a simple approach to insertion.
  436. // Since we already reserved space, we know that this won't
  437. // reallocate the vector.
  438. if (size_t(this->end() - it) >= num_to_insert) {
  439. T* old_end = this->end();
  440. append(std::move_iterator<iterator>(this->end() - num_to_insert),
  441. std::move_iterator<iterator>(this->end()));
  442. // Copy the existing elements that get replaced.
  443. std::move_backward(it, old_end - num_to_insert, old_end);
  444. std::fill_n(it, num_to_insert, elm);
  445. return it;
  446. }
  447. // Otherwise, we're inserting more elements than exist already,
  448. // and we're not inserting at the end.
  449. // Move over the elements that we're about to overwrite.
  450. T* old_end = this->end();
  451. this->set_end(this->end() + num_to_insert);
  452. size_t num_overwritten = old_end - it;
  453. this->uninitialized_move(it, old_end, this->end() - num_overwritten);
  454. // Replace the overwritten part.
  455. std::fill_n(it, num_overwritten, elm);
  456. // Insert the non-overwritten middle part.
  457. std::uninitialized_fill_n(old_end, num_to_insert - num_overwritten, elm);
  458. return it;
  459. }
  460. template <
  461. typename IterType,
  462. typename = typename std::enable_if<std::is_convertible<
  463. typename std::iterator_traits<IterType>::iterator_category,
  464. std::input_iterator_tag>::value>::type>
  465. iterator insert(iterator it, IterType from, IterType to) {
  466. // Convert iterator to elm# to avoid invalidating iterator
  467. // when we reserve()
  468. size_t elm_idx = it - this->begin();
  469. if (it == this->end()) { // Important special case for empty vector.
  470. append(from, to);
  471. return this->begin() + elm_idx;
  472. }
  473. size_t num_to_insert = std::distance(from, to);
  474. // Ensure there is enough space.
  475. reserve(this->size() + num_to_insert);
  476. // Uninvalidate the iterator.
  477. it = this->begin() + elm_idx;
  478. // If there are more elements between the insertion point and
  479. // the end of the range than there are being inserted,
  480. // we can use a simple approach to insertion.
  481. // Since we already reserved space, we know that this won't
  482. // reallocate the vector.
  483. if (size_t(this->end() - it) >= num_to_insert) {
  484. T* old_end = this->end();
  485. append(std::move_iterator<iterator>(this->end() - num_to_insert),
  486. std::move_iterator<iterator>(this->end()));
  487. // Copy the existing elements that get replaced.
  488. std::move_backward(it, old_end - num_to_insert, old_end);
  489. std::copy(from, to, it);
  490. return it;
  491. }
  492. // Otherwise, we're inserting more elements than exist already,
  493. // and we're not inserting at the end.
  494. // Move over the elements that we're about to overwrite.
  495. T* old_end = this->end();
  496. this->set_end(this->end() + num_to_insert);
  497. size_t num_overwritten = old_end - it;
  498. this->uninitialized_move(it, old_end, this->end() - num_overwritten);
  499. // Replace the overwritten part.
  500. for (T* iter = it; num_overwritten > 0; --num_overwritten) {
  501. *iter = *from;
  502. ++iter;
  503. ++from;
  504. }
  505. // Insert the non-overwritten middle part.
  506. this->uninitialized_copy(from, to, old_end);
  507. return it;
  508. }
  509. void insert(iterator it, std::initializer_list<T> init_list) {
  510. insert(it, init_list.begin(), init_list.end());
  511. }
  512. template <typename... ArgTypes>
  513. void emplace_back(ArgTypes&&... args) {
  514. if (megdnn_unlikely(this->m_end_ptr >= this->m_capacity_ptr)) {
  515. this->grow();
  516. }
  517. new (static_cast<void*>(this->end())) T(std::forward<ArgTypes>(args)...);
  518. this->set_end(this->end() + 1);
  519. }
  520. SmallVectorImpl& operator=(const SmallVectorImpl& rhs);
  521. SmallVectorImpl& operator=(SmallVectorImpl&& rhs);
  522. bool operator==(const SmallVectorImpl<T>& rhs) const {
  523. if (this->size() != rhs.size())
  524. return false;
  525. return std::equal(this->begin(), this->end(), rhs.begin());
  526. }
  527. bool operator!=(const SmallVectorImpl<T>& rhs) const { return !(*this == rhs); }
  528. bool operator<(const SmallVectorImpl<T>& rhs) const {
  529. return std::lexicographical_compare(
  530. this->begin(), this->end(), rhs.begin(), rhs.end());
  531. }
  532. };
  533. template <typename T>
  534. void SmallVectorImpl<T>::swap(SmallVectorImpl<T>& rhs) {
  535. if (this == &rhs)
  536. return;
  537. // We can only avoid copying elements if neither vector is small.
  538. if (!this->is_small() && !rhs.is_small()) {
  539. std::swap(this->m_begin_ptr, rhs.m_begin_ptr);
  540. std::swap(this->m_end_ptr, rhs.m_end_ptr);
  541. std::swap(this->m_capacity_ptr, rhs.m_capacity_ptr);
  542. return;
  543. }
  544. if (rhs.size() > this->capacity())
  545. this->grow(rhs.size());
  546. if (this->size() > rhs.capacity())
  547. rhs.grow(this->size());
  548. // Swap the shared elements.
  549. size_t num_shared = this->size();
  550. if (num_shared > rhs.size())
  551. num_shared = rhs.size();
  552. for (size_type i = 0; i != num_shared; ++i)
  553. std::swap((*this)[i], rhs[i]);
  554. // Copy over the extra elms.
  555. if (this->size() > rhs.size()) {
  556. size_t elm_diff = this->size() - rhs.size();
  557. this->uninitialized_move(this->begin() + num_shared, this->end(), rhs.end());
  558. rhs.set_end(rhs.end() + elm_diff);
  559. this->destroy_range(this->begin() + num_shared, this->end());
  560. this->set_end(this->begin() + num_shared);
  561. } else if (rhs.size() > this->size()) {
  562. size_t elm_diff = rhs.size() - this->size();
  563. this->uninitialized_move(rhs.begin() + num_shared, rhs.end(), this->end());
  564. this->set_end(this->end() + elm_diff);
  565. this->destroy_range(rhs.begin() + num_shared, rhs.end());
  566. rhs.set_end(rhs.begin() + num_shared);
  567. }
  568. }
  569. template <typename T>
  570. SmallVectorImpl<T>& SmallVectorImpl<T>::operator=(const SmallVectorImpl<T>& rhs) {
  571. if (this == &rhs)
  572. return *this;
  573. size_t rhs_sz = rhs.size();
  574. size_t cur_sz = this->size();
  575. if (cur_sz >= rhs_sz) {
  576. iterator new_end;
  577. if (rhs_sz) {
  578. new_end = std::copy(rhs.begin(), rhs.end(), this->begin());
  579. } else {
  580. new_end = this->begin();
  581. }
  582. this->destroy_range(new_end, this->end());
  583. this->set_end(new_end);
  584. return *this;
  585. }
  586. if (this->capacity() < rhs_sz) {
  587. // save time for no copy when growing
  588. this->destroy_range(this->begin(), this->end());
  589. this->set_end(this->begin());
  590. cur_sz = 0;
  591. this->grow(rhs_sz);
  592. } else if (cur_sz) {
  593. std::copy(rhs.begin(), rhs.begin() + cur_sz, this->begin());
  594. }
  595. std::uninitialized_copy(rhs.begin() + cur_sz, rhs.end(), this->begin() + cur_sz);
  596. this->set_end(this->begin() + rhs_sz);
  597. return *this;
  598. }
  599. template <typename T>
  600. SmallVectorImpl<T>& SmallVectorImpl<T>::operator=(SmallVectorImpl<T>&& rhs) {
  601. // avoid self assignment
  602. if (this == &rhs)
  603. return *this;
  604. // copy ptr when rhs is small
  605. if (!rhs.is_small()) {
  606. this->destroy_range(this->begin(), this->end());
  607. if (!this->is_small())
  608. free(this->begin());
  609. this->m_begin_ptr = rhs.m_begin_ptr;
  610. this->m_end_ptr = rhs.m_end_ptr;
  611. this->m_capacity_ptr = rhs.m_capacity_ptr;
  612. rhs.reset_to_small();
  613. return *this;
  614. }
  615. size_t rhs_sz = rhs.size();
  616. size_t cur_sz = this->size();
  617. if (cur_sz >= rhs_sz) {
  618. iterator new_end = this->begin();
  619. if (rhs_sz) {
  620. new_end = std::move(rhs.begin(), rhs.end(), new_end);
  621. }
  622. this->destroy_range(new_end, this->end());
  623. this->set_end(new_end);
  624. rhs.clear();
  625. return *this;
  626. }
  627. if (this->capacity() < rhs_sz) {
  628. this->destroy_range(this->begin(), this->end());
  629. this->set_end(this->begin());
  630. cur_sz = 0;
  631. this->grow(rhs_sz);
  632. } else if (cur_sz) {
  633. std::move(rhs.begin(), rhs.begin() + cur_sz, this->begin());
  634. }
  635. this->uninitialized_move(rhs.begin() + cur_sz, rhs.end(), this->begin() + cur_sz);
  636. this->set_end(this->begin() + rhs_sz);
  637. rhs.clear();
  638. return *this;
  639. }
  640. template <typename T, unsigned N>
  641. struct SmallVectorStorage {
  642. typename SmallVectorTemplateCommon<T>::U inline_elms[N - 1];
  643. };
  644. template <typename T>
  645. struct SmallVectorStorage<T, 1> {};
  646. template <typename T>
  647. struct SmallVectorStorage<T, 0> {};
  648. /*!
  649. * \brief This is a 'vector' (really, a variable-sized array), optimized for the
  650. * case when the array is small.
  651. *
  652. * It contains some number of elements in-place,
  653. * which allows it to avoid heap allocation when the actual number of elements
  654. * is below that threshold. This allows normal "small" cases to be fast without
  655. * losing generality for large inputs.
  656. *
  657. * Note that this does not attempt to be exception safe.
  658. *
  659. * SmallVector<T, N>& can be converted to SmallVectorImpl<T>& to erase the
  660. * template param \p N; this is useful for function params.
  661. *
  662. * \tparam T emelment type
  663. * \tparam N number of elements to be stored in the class object
  664. */
  665. template <typename T, unsigned N = 4>
  666. class SmallVector : public SmallVectorImpl<T> {
  667. SmallVectorStorage<T, N> m_storage;
  668. public:
  669. SmallVector() : SmallVectorImpl<T>(N) {}
  670. explicit SmallVector(size_t size, const T& value = T()) : SmallVectorImpl<T>(N) {
  671. this->assign(size, value);
  672. }
  673. template <
  674. typename IterType,
  675. typename = typename std::enable_if<std::is_convertible<
  676. typename std::iterator_traits<IterType>::iterator_category,
  677. std::input_iterator_tag>::value>::type>
  678. SmallVector(IterType first, IterType last) : SmallVectorImpl<T>(N) {
  679. this->append(first, last);
  680. }
  681. SmallVector(std::initializer_list<T> init_list) : SmallVectorImpl<T>(N) {
  682. this->assign(init_list);
  683. }
  684. SmallVector(const SmallVector& rhs) : SmallVectorImpl<T>(N) {
  685. if (!rhs.empty())
  686. SmallVectorImpl<T>::operator=(rhs);
  687. }
  688. ~SmallVector() {}
  689. const SmallVector& operator=(const SmallVector& rhs) {
  690. SmallVectorImpl<T>::operator=(rhs);
  691. return *this;
  692. }
  693. SmallVector(SmallVector&& rhs) : SmallVectorImpl<T>(N) {
  694. if (!rhs.empty())
  695. SmallVectorImpl<T>::operator=(std::move(rhs));
  696. }
  697. SmallVector(SmallVectorImpl<T>&& rhs) : SmallVectorImpl<T>(N) {
  698. if (!rhs.empty())
  699. SmallVectorImpl<T>::operator=(std::move(rhs));
  700. }
  701. const SmallVector& operator=(SmallVector&& rhs) {
  702. SmallVectorImpl<T>::operator=(std::move(rhs));
  703. return *this;
  704. }
  705. const SmallVector& operator=(SmallVectorImpl<T>&& rhs) {
  706. SmallVectorImpl<T>::operator=(std::move(rhs));
  707. return *this;
  708. }
  709. const SmallVector& operator=(std::initializer_list<T> init_list) {
  710. this->assign(init_list);
  711. return *this;
  712. }
  713. };
  714. template <typename T, unsigned n>
  715. static inline size_t capacity_in_bytes(const SmallVector<T, n>& vec) {
  716. return vec.capacity_in_bytes();
  717. }
  718. template <typename T>
  719. inline typename SmallVectorImpl<T>::const_iterator find(
  720. const SmallVectorImpl<T>& vec, const T& value) {
  721. return vec.find(vec.begin(), vec.end(), value);
  722. }
  723. } // end namespace megdnn
  724. #include "megdnn/internal/visibility_epilogue.h"
  725. namespace std {
  726. /// Implement std::swap in terms of SmallVector swap.
  727. template <typename T>
  728. inline void swap(megdnn::SmallVectorImpl<T>& lhs, megdnn::SmallVectorImpl<T>& rhs) {
  729. lhs.swap(rhs);
  730. }
  731. /// Implement std::swap in terms of SmallVector swap.
  732. template <typename T, unsigned N>
  733. inline void swap(megdnn::SmallVector<T, N>& lhs, megdnn::SmallVector<T, N>& rhs) {
  734. lhs.swap(rhs);
  735. }
  736. } // end namespace std
  737. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台