Out of bounds issue (with scatter)

Out of bounds issue (with scatter)

Hello,

I'm trying to use scatter(..) function:

template
dense
scatter(const dense& source, const dense& index, const dense& defaults)

with indices (see par "index") partly out of bounds for source container.

As result I'm getting run time exeption:

terminate called after throwing an instance of 'arbb_2::out_of_bounds'
what(): A container was accessed out of bounds: INDEX_OUT_BOUNDS: Index out of bounds
Aborted

Could someone help me and tell is it ok and what should I do in such cases?

P.S. I'm using currently env ARBB_OPT_LEVEL=O0 and func(...) instead of call(func)(...)

9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi, Happy New Year! Please drop the snippet of code that reproduces the problem and also the results you get with O2 and O3. I don't think I have enough information to solve the problem just looking at the error message.

Thanks,

Noah

Happy New Year!

Here is the example:

#include
using namespace arbb;

void test_scatter() {
dense i = indices(0,3,1);
i[0] = -1;

dense sourse = indices(0,3,1);
dense result = fill(0,16);

result = scatter( sourse, i, result );
}

int main(int /*argc*/, char* /*argv*/[])
{
test_scatter();
return 1;

}

results with O0, O2 and O3 are same:

terminate called after throwing an instance of 'arbb_2::out_of_bounds'
what(): A container was accessed out of bounds: INDEX_OUT_BOUNDS: Index out of bounds

When using scatter, the arguments are as follows:

1st argument = source, from where we pick elements one-by-one, from beginning to the end.

2nd argument = indices at the destination. For each element picked from 1st argunebt, put it into the destination container at the position specified by an index.

3rd argument = default values. At the destination, if some positions do not have values after scatter, these blank slots are filled with corresponding values from the 3rd argument.

Because you declared i[0] = -1, it is clear you wanted to put the first element picked from source to the destination at position -1. But there isn't position -1. Positions always start from 0.

When you are creating an ArBB dense container, you first need to populate it using bind() or the range interface. We have knowledge base articles covering both of these methods in addition to the User's Guide covering it in great detail.

Next, in the main(), you need to use call() to invoke "test_scatter". However,"test_scatter" as is written is not an ArBB function and will not work since it doesn't follow the proper ArBB function signature(since it does not take any ArBB containers as arguments).

Noah Clemons,

Thanks for answer!

Because you declared i[0] = -1, it is clear you wanted to put the first element picked from source to the destination at position -1. But there isn't position -1. Positions always start from 0.

Here I want to do nothing with the correspondent element of "index" and "result". It just should not change.

So, if I have to deal with indices some of which can be out of bounds, I should write the scatter function by my own? Is this correct?

It is not very clear what you mean by out-of-bounds indices. It will be helpful if you can write a few lines of plain C code to show your intention. It's probably something not directly supported by the scatter API, but could be done some other way.

Zhang Z,

It my case out-of-bounds means -1 for i16, or max_value_of_usize when they will be converted in dense, which is type of scatter function parameter.

But I'm not sure that I understand you. I've shown the code example:

void test_scatter() {
dense i = indices(0,3,1);
i[0] = -1;

dense sourse = indices(0,3,1);
dense result = fill(0,16);

result = scatter( sourse, i, result );
}

here indices "i" are filled by hands, but of course in program they are filled during some computations and I cannot force them to be all in bounds ( except extreme ways as repacking of containers or adding additional (result.lenght()+1)-th element in result and changing -1 to "result.lenght()" )

Here is what the API manual says about arbb::scatter (for the particular version of scatter you are using):

template
dense arbb::scatter (const dense< T, 1 > &source, const dense< usize, 1 > &index, const dense< T, 1 > &defaults)

"Returns a dense container with the same size as defaults, data from source scattered into the locations in index, and elements set to the corresponding elements in defaults if not otherwise initialized."

From this we can see that the 2nd argument passed to the function (dense 'i' in your code) is used to decide the final locations of elements in the result after being scattered. Elements in the 2nd argument is expected to be 'usize' type. So a -1 might be converted to the max value of 'usize', which is certainly far out of the bound of the container to be returned. There's no surprise an "out-of-bound" exception is thrown. Also note that the returned container always has the same size of the 3rd argument. So scattering to out-of-bounds locations is not possible.

Probably an example can help us here. In your code, the 1st argument (source) is

[0, 1, 2]

The 2nd argument (i) is

[-1, 1, 2]

The 3rd argument (result) is

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Would you please explain what you want to see in the returned container after calling scatter?

Thanks,
Zhang

"Returns a dense container with the same size as defaults, data from source scattered into the locations in index, and elements set to the corresponding elements in defaults if not otherwise initialized."

Oh. Thanks for pointing this out. I obviously misunderstood role of the 3rd argument (defaults).

In your code, the 1st argument (source) is
[0, 1, 2]
The 2nd argument (i) is
[-1, 1, 2]
The 3rd argument (result) is
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]


To build more clear example let's change my function on

void test_scatter() {
dense i = indices(0,3,1);
i[0] = -1;

const dense sourse = indices(0,3,1);
const dense defaults = fill(1
0,16);

dense result = scatter( sourse, i, defaults );
}


then


the 1st argument (source) is
[0, 1, 2]
The 2nd argument (i) is
[-1, 1, 2]
The 3rd argument (defaults) is
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]


and I would like the result to be[10, 1, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]

one of the obvious solutions is

template
dense
scatter_my(const dense& source, const dense& index, const dense& defaults)
{
dense result;
const dense mask = index <defaults.length();

const dense sourceInBounds = pack(source, mask);

const dense indexInBounds = pack(index, mask);

result = scatter(sourceInBounds,indexInBounds,defaults );
return result;
}

but the question now is will it be efficient enough from the execution time point of view?

Leave a Comment

Please sign in to add a comment. Not a member? Join today