Tensorflow GATHER error

I got error when I use benchmark
ERROR: tensorflow/lite/kernels/gather.cc:182 indices_has_only_positive_elements was not true.
ERROR: gather index out of bounds
ERROR: Node number 6 (GATHER) failed to invoke.
but I don’t get it…
why does this error occurs?

@rita19991020,

Could you please share standalone code to reproduce the issue?

Thank you!

TfLiteStatus SimpleMemoryArena::Allocate(
TfLiteContext* context, size_t alignment, size_t size, int32_t tensor,
int32_t first_node, int32_t last_node,
ArenaAllocWithUsageInterval* new_alloc) {
TF_LITE_ENSURE(context, alignment <= arena_alignment_);
new_alloc->tensor = tensor;
new_alloc->first_node = first_node;
new_alloc->last_node = last_node;
new_alloc->size = size;
if (size == 0) {
new_alloc->offset = 0;
return kTfLiteOk;
}
// If we don’t find a better gap just allocate at the end of the buffer.
const size_t kOffsetNotAssigned = std::numeric_limits<size_t>::max();
size_t best_offset = kOffsetNotAssigned;
size_t best_offset_fit = kOffsetNotAssigned;

// Go through the sorted allocs and look at the gaps between them.
size_t current_offset = 0;
for (const auto& alloc : active_allocs_) {
if (alloc.last_node < first_node || alloc.first_node > last_node) {
// Usage interval of alloc doesn’t intersect with current tensor’s usage
// interval, so we skip it.
continue;
}
size_t aligned_current_offset = AlignTo(alignment, current_offset);
// If we found a gap larger than required size, and smaller than previous
// best fit, take it.
if (aligned_current_offset + size <= alloc.offset &&
alloc.offset - aligned_current_offset < best_offset_fit) {
best_offset = aligned_current_offset;
best_offset_fit = alloc.offset - current_offset;
}
current_offset = std::max(current_offset, alloc.offset + alloc.size);
// A gap of zero is as good as it gets, no point continuing.
if (best_offset_fit == 0) {
break;
}
}
if (best_offset == kOffsetNotAssigned) {
best_offset = AlignTo(alignment, current_offset);
}

// Update the required buffer size.
high_water_mark_ = std::max(high_water_mark_, best_offset + size);
new_alloc->offset = best_offset;

auto insertion_it = std::upper_bound(active_allocs_.begin(),
active_allocs_.end(), *new_alloc);
active_allocs_.insert(insertion_it, *new_alloc);
return kTfLiteOk;
}

actually, I changed this code to make every tensors to get offset=0
Then the error occurs…

If every tensor has an offset of zero, that means that all tensors share the same memory so tensor data is overwritten which will cause at best wrong results and at worst undefined behaviour. Safe guards in the gather op prevent UB here. Since all tensors share the same buffer, the indices for the gather op are being over written causing some of them to become negative and therefore invalid. What are you trying to achieve by changing the internal memory arena code?

As an aside, you must be careful using the benchmark tool with models with gather ops. The indices passed to the gather op must be valid indices (> 0 and < tensor size) otherwise there will be an error. The benchmark tool allows you to control the contents of the input tensor. Take a look at the documentation for the flags.

thanks for reply!

could you share the part of code that make index negative?