EDIT: I added a clearer question as a reply to this comment. I decided to leave this just to give some context to the previously shared code and rationale on why the question I asked here would not help to solve the original question.
Looking at the code, b refers to the batch to which each target belongs to.
I think I found the problem, but I don’t have a clear idea on how to solve it. After more debugging, I understand that since the targets are being split, I needed to modify them somehow.
The targets are built as follows, here image_number refers to the batch index for each box:
[image_number, class_label, x, y, w, h]

And since there can be different amounts of objects in each image, the target tensor size varies.
In the targets, b is an array that can have values between [0, gB-1] where gB is the global batch size, and obj_mask second dimension will have a size of nB  which is the batch size in the current GPU. In single GPU mode b is equal to nB and everything works fine.
But when using multiple GPUs, the values of b can still be between [0, gB-1] where the obj_mask second dimension will have a size gB/2. Here is where the assertion error is being triggered.
As a first solution, I thought to just check in which device the code is running. If it is running in the second GPU, just shift b's values by the batch size, here nB is the split batch size:
if obj_mask.device.index > 0:
    for i in range(len(b[i])):
        if b[i] > nB-1:
            b[i] = target[i,0]-nB

But the problem I encountered with this approach is that there is no way of knowing if one image may have many more objects than the others. So when target is split, this unbalance may result in b having a range of values [0, gB-1], and I couldn’t do the offset because then different batches may have the same index in the targets.
Here is a pseudo-code example of one of the cases where this is true:
#These are the global values
gB = 16
target[:,0] = 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15]
#len(target[:,0]) = 67

#In GPU 0, after the split
nB = 8
obj_mask = BoolTensor(nB, 3, 22, 22).fill_(0)

b = target[:,0][ : len(target[:,0])//2]
b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
#len(b) = 33
obj_mask[b, 0, 0, 0] = 1

#In GPU 1, after the split
nB = 8
obj_mask = BoolTensor(nB, 3, 22, 22).fill_(0)
b = target[:,0][len(target[:,0])//2 : ]
b = [0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15]
#len(b) = 34
obj_mask[b, 0, 0, 0] = 1

Here it can be seen that since image zero has the most amount of boxes, when the split is done, the range of values of b in GPU 1 will trigger the assertion. But if I apply the solution I came up with, the following will happen:
#In GPU 1
b = [0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15]

if obj_mask.device.index > 0:
    for i in range(len(b[i])):
        if b[i] > nB-1:
            b[i] = target[i,0]-nB

b = [0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7]

My new question now is, how could I evade this problem if the targets do not have always a specific shape?
My main idea would be to modify the way the targets are built by creating them in with a shape of [gB, max_Boxes, 6], where I would have to check the maximum amount of boxes (max_Boxes) in a batch and fill with zeroes on the other ones so that the tensors can be appended to form the targets. I am not a fan of this approach since it would require me to modify a big amount of code, but I will do it if I have to.
So if anyone could come up with a different strategy, it would be most appreciated!
Thanks for taking the time of reading such long post.