1

Is there such a thing like

af::array groupedMax= af::Max(myValues, fromIndices, toIndices);

For example,

myValues= {random values}
fromIndices = {2, 7, 5}
toIndices = {10, 9, 12}

The result should be

groupedMax[0] will be max between myValues[2] and myValues[10]
groupedMax[1] will be max between myValues[7] and myValues[9]
groupedMax[2] will be max between myValues[5] and myValues[12]

Is this achievable? If not, any idea how to do this super fast on ArrayFire?

Edit: Here is a rough single threaded code I want to achieve.

vector<double> groupedMaxValues(fromIndices.size());
for(int g=0; g<fromIndices.size(); g++)
{
  double maxVal = 0;
  for(int i=fromIndices[g]; i<=toIndices[g]; i++)
  {
    if(maxVal < myValues[i])
    {
      maxVal = myValues[i];
    }
  }
  groupedMaxValues[g] = maxVal;
}
BoBoDev
  • 847
  • 1
  • 8
  • 17

2 Answers2

1

I am not aware of what is a grouped max, but the operation of max between two af::arrays can be performed using the following

af::array a = myValues(fromIndices);
af::array b = myValues(toIndices);
af::array cond = a > b;
af::array mxd = cond * a + (1 - cond) * b;

In the above example, the two inputs a & b are just indexed arrays of myValues.

Update: (6th Sep, 2019) After BoBoDev latest comment on this answer, here is the code I came up with following code snippet based on your explanation and it gives the correct output(shown after the code)

    float v[] = {10.0f, 30.0f, 20.0f};
    af::array myValues(3, 1, v);

    int f4m[] = {10};
    int to[] = {12};

    af::array fromIndices(1, f4m);
    af::array toIndices(1, to);

    af_print(myValues);
    af_print(fromIndices);
    af_print(toIndices);

    af::array a = myValues(fromIndices);
    af::array b = myValues(toIndices);
    af::array cond = a > b;
    af::array mxd = cond * a + (1 - cond) * b;

    af_print(mxd);

Output of sample

myValues
[3 1 1 1]
   10.0000 
   30.0000 
   20.0000 

fromIndices
[1 1 1 1]
        10 
toIndices
[1 1 1 1]
        12 
mxd
[1 1 1 1]
   30.0000 
pradeep
  • 712
  • 4
  • 13
  • Hello, thanks for answering, but, this code doesn't know anything between the from and to indices. For example if my from index 10 to 12, I have value {10, 30, 20}, your code only returns 20. – BoBoDev Aug 19 '19 at 20:21
  • Based on your original description, I understood that you fromIndices and toIndices are of same length, and your output should do a element-wise max of the sets described by the indices from the original main set(input). The code suggested will do the above operation if and only if fromIndices and toIndices are of same length. If you are certain something is wrong in the code, can you please create a minimal working example and share it so that I can check out what you are trying to achieve. – pradeep Sep 04 '19 at 06:21
  • Hello, if my comment is still confusing to you, I will repeat it again. For example if fromIndex is 10 and ToIndex is 12, I have value {10, 30, 20} between the FROM and TO index, my expected result should be 30, not 20. Does this comment answer clear up the ambiguity you see? – BoBoDev Sep 05 '19 at 14:56
  • @BoBoDev I have updated the answer with sample code and output for your example. I am not getting 20 as you claim. Please check updated section in the answer. Which version of ArrayFire are you using ? – pradeep Sep 06 '19 at 15:44
  • Hello @pradeep, can you print out a and b as well? I have not ever seen a and b initialized like this. I will try this when I get to the office on Monday. Thanks for helping. – BoBoDev Sep 07 '19 at 19:43
  • Hello @pradee, I don't know why a is 30 and b is 20 when the from and to index is out of bound. In order to use index 10 and 12, the v[] must have a least 13 values. Your code is the same as af::max(a, b), which is not what I am looking for based on the single threaded code I have added. But, thanks for the help. – BoBoDev Sep 09 '19 at 20:41
  • For an array indexed using another array, there is no valid way to error out for out of bound indices in the middle of GPU kernel execution. Hence, we map out of bound indices to valid range. – pradeep Sep 11 '19 at 11:20
0

Sorry,I was confused by the original description. Your serial code explains the Q in much better way.

I think what you are looking for is af::scanByKey - http://arrayfire.org/docs/group__scan__func__scanbykey.htm - although I am not yet sure on how to generate keys for your use case as the indices range (from-to) seem to overlap. The length of the ranges also doesn't seem to be same.

pradeep
  • 712
  • 4
  • 13
  • The scanByKey sounds like a possibility, although I don't know how to use it yet. My actual use case actually does not overlap, so, if that's what the single key array is for, it is ok. The range is different, but, this method sounds like it should work. – BoBoDev Sep 14 '19 at 03:05