Instructions to use ZibinDong/ActionCodec2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ZibinDong/ActionCodec2 with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("ZibinDong/ActionCodec2", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download actioncodec2_kernels/common.hpp from ZibinDong/ActionCodec2: direct link, hf CLI and curl.
- Browser
- Download file 3.74 kB
-
https://huggingface.co/ZibinDong/ActionCodec2/resolve/main/actioncodec2_kernels/common.hpp
- Command line
-
hf download hf://ZibinDong/ActionCodec2/actioncodec2_kernels/common.hpp
-
curl -L -o common.hpp https://huggingface.co/ZibinDong/ActionCodec2/resolve/main/actioncodec2_kernels/common.hpp
3.74 kB
| // Shared primitives for the ActionCodec2 native kernels. | |
| namespace ac2 { | |
| class CounterMap { | |
| public: | |
| static constexpr uint64_t kEmpty = ~0ull; | |
| explicit CounterMap(size_t capacity_hint = 1024) { reserve(capacity_hint); } | |
| void reserve(size_t entries) { | |
| size_t target = 16; | |
| while (target * 3 < entries * 4) target <<= 1; // keep load factor <= 0.75 | |
| if (target <= mask_ + 1 && !keys_.empty()) return; | |
| rehash(target); | |
| } | |
| size_t size() const { return size_; } | |
| size_t buckets() const { return mask_ + 1; } | |
| void clear() { | |
| std::fill(keys_.begin(), keys_.end(), kEmpty); | |
| size_ = 0; | |
| } | |
| int64_t get(uint64_t key) const { | |
| size_t slot = probe(key); | |
| return keys_[slot] == key ? values_[slot] : 0; | |
| } | |
| int64_t add(uint64_t key, int64_t delta) { | |
| return add_with_previous(key, delta).second; | |
| } | |
| // Update and expose both values with one hash-table probe. This is useful | |
| // when a caller must distinguish a newly observed key from a stale one. | |
| std::pair<int64_t, int64_t> add_with_previous(uint64_t key, int64_t delta) { | |
| size_t slot = probe(key); | |
| if (keys_[slot] != key) { | |
| if ((size_ + 1) * 4 > (mask_ + 1) * 3) { | |
| rehash((mask_ + 1) << 1); | |
| slot = probe(key); | |
| } | |
| keys_[slot] = key; | |
| values_[slot] = 0; | |
| ++size_; | |
| } | |
| const int64_t previous = values_[slot]; | |
| values_[slot] += delta; | |
| return {previous, values_[slot]}; | |
| } | |
| template <typename Fn> | |
| void for_each(Fn&& fn) const { | |
| for (size_t slot = 0; slot <= mask_; ++slot) { | |
| if (keys_[slot] != kEmpty && values_[slot] != 0) fn(keys_[slot], values_[slot]); | |
| } | |
| } | |
| size_t live_entries() const { | |
| size_t live = 0; | |
| for (size_t slot = 0; slot <= mask_; ++slot) { | |
| if (keys_[slot] != kEmpty && values_[slot] != 0) ++live; | |
| } | |
| return live; | |
| } | |
| private: | |
| static uint64_t mix(uint64_t value) { // splitmix64 finalizer | |
| value ^= value >> 30; | |
| value *= 0xbf58476d1ce4e5b9ull; | |
| value ^= value >> 27; | |
| value *= 0x94d049bb133111ebull; | |
| return value ^ (value >> 31); | |
| } | |
| size_t probe(uint64_t key) const { | |
| size_t slot = mix(key) & mask_; | |
| while (keys_[slot] != kEmpty && keys_[slot] != key) slot = (slot + 1) & mask_; | |
| return slot; | |
| } | |
| void rehash(size_t buckets) { | |
| std::vector<uint64_t> old_keys; | |
| std::vector<int64_t> old_values; | |
| old_keys.swap(keys_); | |
| old_values.swap(values_); | |
| keys_.assign(buckets, kEmpty); | |
| values_.assign(buckets, 0); | |
| mask_ = buckets - 1; | |
| size_ = 0; | |
| for (size_t slot = 0; slot < old_keys.size(); ++slot) { | |
| if (old_keys[slot] != kEmpty && old_values[slot] != 0) { | |
| size_t target = probe(old_keys[slot]); | |
| keys_[target] = old_keys[slot]; | |
| values_[target] = old_values[slot]; | |
| ++size_; | |
| } | |
| } | |
| } | |
| std::vector<uint64_t> keys_; | |
| std::vector<int64_t> values_; | |
| size_t mask_ = 0; | |
| size_t size_ = 0; | |
| }; | |
| struct HeapEntry { | |
| int64_t count; | |
| uint64_t key; | |
| uint32_t version; // only shifted temporal self-rules use this | |
| }; | |
| struct HeapOrder { | |
| bool operator()(const HeapEntry& a, const HeapEntry& b) const { | |
| if (a.count != b.count) return a.count < b.count; // larger count first | |
| return a.key > b.key; // smaller key first | |
| } | |
| }; | |
| inline void heap_push(std::vector<HeapEntry>& heap, const HeapEntry& entry) { | |
| heap.push_back(entry); | |
| std::push_heap(heap.begin(), heap.end(), HeapOrder{}); | |
| } | |
| inline HeapEntry heap_pop(std::vector<HeapEntry>& heap) { | |
| std::pop_heap(heap.begin(), heap.end(), HeapOrder{}); | |
| HeapEntry top = heap.back(); | |
| heap.pop_back(); | |
| return top; | |
| } | |
| } // namespace ac2 | |