| 4156 | } |
| 4157 | |
| 4158 | struct ggml_tensor * ggml_axpy( |
| 4159 | struct ggml_context * ctx, |
| 4160 | struct ggml_tensor * a, |
| 4161 | struct ggml_tensor * b, |
| 4162 | struct ggml_tensor * sparse_idx, |
| 4163 | // Under CPU + GPU hybrid inference: |
| 4164 | // When using GPU, this tensor is gpu_bucket to map the index back to the original tensor; |
| 4165 | // When using CPU, this tensor is gpu_index to indicate which row are offloaded to GPU. |
| 4166 | // Under full GPU/GPU inference, it is NULL. |
| 4167 | struct ggml_tensor * hybrid_aux) { |
| 4168 | GGML_ASSERT(a != NULL && b != NULL); |
| 4169 | GGML_ASSERT(!ggml_is_transposed(a)); |
| 4170 | bool is_node = false; |
| 4171 | |
| 4172 | if (a->grad || b->grad) { |
| 4173 | is_node = true; |
| 4174 | } |
| 4175 | |
| 4176 | const int64_t ne[4] = { a->ne[0], b->ne[1], b->ne[2], b->ne[3] }; |
| 4177 | struct ggml_tensor * result = ggml_new_tensor(ctx, GGML_TYPE_F32, MAX(a->n_dims, b->n_dims), ne); |
| 4178 | |
| 4179 | result->op = GGML_OP_AXPY; |
| 4180 | result->grad = is_node ? ggml_dup_tensor(ctx, result) : NULL; |
| 4181 | result->src[0] = a; |
| 4182 | result->src[1] = b; |
| 4183 | result->src[2] = sparse_idx; |
| 4184 | result->src[3] = hybrid_aux; |
| 4185 | |
| 4186 | int32_t params[] = { hybrid_aux ? 0 : 1 }; |
| 4187 | ggml_set_op_params(result, params, sizeof(params)); |
| 4188 | |
| 4189 | return result; |
| 4190 | } |
| 4191 | |
| 4192 | // ggml_out_prod |
| 4193 |
no test coverage detected