Why there is no "Concat" operation in IBackEnd interface(since v1.4)?

Since upgrading from 1.3 to 1.4/1.6, the Concat operation in the IBackend interface has disappeared. Has it been removed or renamed? This operation is crucial to my project. Are there any alternative methods?
(Edit: After digged the changelog,I found there is a new API ‘sliceset’ for concat operation,but how to use it as concate serval tensors into one axis? Is there any samples for it? )

1 Like

+1 for the feedback that there should be a simple Concat method, even if it just wraps the existing SliceSet method. Here’s what I’m currently doing in an extension method in case it’s useful: (no guarantees for correctness, but works for me so far)

public static class IBackendExtensions {
    public static Tensor Concat(this IBackend backend, Tensor[] tensors, Tensor O, int axis) {
        if (O.shape.HasZeroDims())
            return O;
        int start = 0;
        foreach (var tensor in tensors) {
            backend.SliceSet(tensor, O, axis, start, 1);
            start += tensor.shape[axis];
        }
        return O;
    }
}

To get the output tensor shape I also need to readd this helper class:

internal static class TensorShapeHelper {

    public static TensorShape ConcatShape(Tensor[] tensors, int axis) {
        TensorShape output = tensors[0].shape;

        for (int i = 1; i < tensors.Length; ++i) {
            TensorShape shape = tensors[i].shape;
            output = output.Concat(shape, axis);
        }

        return output;
    }
}

Then you can allocate the output tensor from the array of tensors like so

var O = TensorFloat.AllocNoData(TensorShapeHelper.ConcatShape(tensors, axis));
// or
var O = TensorInt.AllocNoData(TensorShapeHelper.ConcatShape(tensors, axis));

1 Like

Got it. Thanks much

var start = 0;
for (var i = 0; i < inputs.Length; i++)
{
      var X = inputs[i];
      var length = X.shape[axis];
      if (length == 0)
            continue;
      backend.SliceSet(X, O, axis, start, 1);
      start += length;
}

Although I’d strongly recommend moving to the functional API

1 Like