| 182 | } |
| 183 | |
| 184 | void ggml_backend_tensor_copy(struct ggml_tensor * src, struct ggml_tensor * dst) { |
| 185 | //printf("src: %s ne: [%d %d %d %d] nb: [%d %d %d %d]\n", src->name, (int)src->ne[0], (int)src->ne[1], (int)src->ne[2], (int)src->ne[3], (int)src->nb[0], (int)src->nb[1], (int)src->nb[2], (int)src->nb[3]); |
| 186 | //printf("dst: %s ne: [%d %d %d %d] nb: [%d %d %d %d]\n", dst->name, (int)dst->ne[0], (int)dst->ne[1], (int)dst->ne[2], (int)dst->ne[3], (int)dst->nb[0], (int)dst->nb[1], (int)dst->nb[2], (int)dst->nb[3]); |
| 187 | GGML_ASSERT(ggml_are_same_layout(src, dst) && "cannot copy tensors with different layouts"); |
| 188 | |
| 189 | // fprintf(stderr, "cpy tensor %s from %s to %s (%lu bytes)\n", src->name, ggml_backend_name(src->backend), ggml_backend_name(dst->backend), ggml_nbytes(src)); |
| 190 | |
| 191 | if (src == dst) { |
| 192 | return; |
| 193 | } |
| 194 | |
| 195 | // TODO: allow backends to support copy to/from same backend |
| 196 | |
| 197 | if (ggml_get_backend(dst)->iface.cpy_tensor_from != NULL) { |
| 198 | ggml_get_backend(dst)->iface.cpy_tensor_from(ggml_get_backend(dst)->context, src, dst); |
| 199 | } else if (ggml_get_backend(src)->iface.cpy_tensor_to != NULL) { |
| 200 | ggml_get_backend(src)->iface.cpy_tensor_to(ggml_get_backend(src)->context, src, dst); |
| 201 | } else { |
| 202 | // shouldn't be hit when copying from/to CPU |
| 203 | #ifndef NDEBUG |
| 204 | fprintf(stderr, "ggml_backend_tensor_copy: neither cpy_tensor_from nor cpy_tensor_to are implemented for backends %s and %s, falling back to get/set\n", ggml_backend_name(src->buffer->backend), ggml_backend_name(dst->buffer->backend)); |
| 205 | #endif |
| 206 | size_t nbytes = ggml_nbytes(src); |
| 207 | void * data = malloc(nbytes); |
| 208 | ggml_backend_tensor_get(src, data, 0, nbytes); |
| 209 | ggml_backend_tensor_set(dst, data, 0, nbytes); |
| 210 | free(data); |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | // backend CPU |
| 215 |
no test coverage detected