MCPcopy Create free account
hub / github.com/cactus-compute/cactus / compute_embedding_node

Function compute_embedding_node

cactus/graph/graph_ops_tensor.cpp:202–314  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

200}
201
202void compute_embedding_node(GraphNode& node, const std::vector<std::unique_ptr<GraphNode>>& nodes, const std::unordered_map<size_t, size_t>& node_index_map) {
203 const auto& embeddings_buffer = get_input(node, 0, nodes, node_index_map);
204 const auto& indices_buffer = get_input(node, 1, nodes, node_index_map);
205
206 size_t hidden_dim = embeddings_buffer.shape[1];
207 size_t num_indices = indices_buffer.total_size;
208 size_t vocab_size = embeddings_buffer.original_N > 0
209 ? embeddings_buffer.original_N
210 : embeddings_buffer.shape[0];
211
212 std::vector<float> indices_float;
213 const float* indices_ptr;
214 if (indices_buffer.precision == Precision::FP32) {
215 indices_ptr = indices_buffer.data_as<float>();
216 } else {
217 indices_float.resize(num_indices);
218 const int8_t* int_indices = indices_buffer.data_as<int8_t>();
219 for (size_t i = 0; i < num_indices; i++) {
220 indices_float[i] = static_cast<float>(int_indices[i]);
221 }
222 indices_ptr = indices_float.data();
223 }
224
225 __fp16* output = node.output_buffer.data_as<__fp16>();
226
227 Precision emb_prec = embeddings_buffer.precision;
228 if (PrecisionTraits::is_integer(emb_prec) && embeddings_buffer.group_size > 0) {
229 const int8_t* embeddings = embeddings_buffer.data_as<int8_t>();
230 const __fp16* scales = embeddings_buffer.scales_as_fp16();
231 size_t group_size = embeddings_buffer.group_size;
232 size_t num_groups = embeddings_buffer.num_groups;
233
234 static const uint8_t gather_indices[4][16] = {
235 {0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51}, // lane 0
236 {4, 5, 6, 7, 20, 21, 22, 23, 36, 37, 38, 39, 52, 53, 54, 55}, // lane 1
237 {8, 9, 10, 11, 24, 25, 26, 27, 40, 41, 42, 43, 56, 57, 58, 59}, // lane 2
238 {12, 13, 14, 15, 28, 29, 30, 31, 44, 45, 46, 47, 60, 61, 62, 63} // lane 3
239 };
240
241 auto load_table = [emb_prec](const int8_t* base) -> int8x16x4_t {
242 if (emb_prec == Precision::INT4) {
243 const uint8_t* ubase = reinterpret_cast<const uint8_t*>(base);
244 int8x16_t low_a, high_a, low_b, high_b;
245 unpack_int4_as_int8x16x2(ubase, high_a, low_a);
246 unpack_int4_as_int8x16x2(ubase + 16, high_b, low_b);
247 return {low_a, high_a, low_b, high_b};
248 }
249 return vld1q_s8_x4(base);
250 };
251
252 for (size_t i = 0; i < num_indices; i++) {
253 size_t idx = static_cast<size_t>(indices_ptr[i]);
254 if (idx >= vocab_size) {
255 throw std::runtime_error("Embedding index out of bounds: " + std::to_string(idx) + " >= " + std::to_string(vocab_size));
256 }
257
258 size_t block = idx / 4;
259 size_t lane = idx % 4;

Callers

nothing calls this directly

Calls 3

unpack_int4_as_int8x16x2Function · 0.85
dataMethod · 0.80
scales_as_fp16Method · 0.80

Tested by

no test coverage detected