cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

WTrei
Journeyman III

Strange Brook behavior

Returned value from subkernel behave in a very strage way (caused by if clauses)

To make a long storry short: I am sick of brook!

The longer version:

I tried to write a modular multiplikation function for 124 Bit unsigned. (I use 4 32 bit integers to emulate them, but leaving out the highest bit).

 

Now I wanted to test my function an became some errors, so i started testig:

kernel uint4 multMod(uint4 input1, uint4 input2, uint4 modulus, int mode) {

   ...
   /* some not importand calculations here */
   ...
    //return doublePres0;                                                   <-- 1

    if (compare(doublePres1,myNull) == 0)  {
        // return doublePres0;                                              <-- 2
        if (compare(doublePres0,modulus) == -1)  {
            // return doublePres0;                                          <-- 3
        }
    }

    //return doublePres0;                                                   <-- 4

 

In this code you can see 4 positions where values could be returned. The "compare" operation is just something like "(input1.w > input2.w){ return -1 }" and so on, so it doesn't change its inputs.

Position 1 and 4 are working fine, the results seem to be correct (input ist 0 0 0 2, output is 0 0 0 4). At position 2 some thrash is returned (3f800000 xxxxxxxx 0 4 )  with the z-part (xxxx....) changing!!!! (with all threads becomming the same input) and last but not least at position 3 just zeros are returned!

I don't know what happens here but I hope there is a immidiate way to fix, because this stuff makes stream computing impossible to use

Ps: I hope you're able to understand the problem - my english is very poor. If nesesary i would send the whole code.

0 Likes
10 Replies
hagen
Journeyman III

If the first if() isn't true, neither position 2 nor 3 will execute.  So the return value is undefined, which may be what you are seeing.  Brook+ will return garbage if you fail to assign a value to an output stream.

You can just try initializing doublePres0 to something like unit4(9,9,9,9) at the top and check your output again at each of the 4 different positions.

0 Likes

Things are getting more and more strange:

I tried to initialize doublePres0 and what comes out is ... more strage than the problem before:

 

uint4 doublePres0 = uint4( (unsigned) 0, (unsigned) 0, (unsigned) 0, (unsigned) 0);
    uint4 doublePres1 = uint4( (unsigned) 0, (unsigned) 0, (unsigned) 0, (unsigned) 0);
   
    uint4 tmp1 = multiplyUInt124Low(input1,input2);
    uint4 tmp2 = multiplyUInt124Mid(input1,input2, tmp1);
    doublePres0.xy = tmp1.xy;
    doublePres0.zw = tmp2.xy;
    doublePres1 = multiplyUInt124High(input1,input2, tmp2);   

    // doublePres0 = uint4( (unsigned) 7, (unsigned) 7, (unsigned) 7, (unsigned) 7);


    //return doublePres0;                                       
    if (compare(doublePres1,myNull) == 0)  {
        // return doublePres0;                                 
        if (compare(doublePres0,modulus) == -1)  {
            // return doublePres0;
        }
    }
    // return doublePres0;

 

 

With the "doublePres0 = uint4( (unsigned) 7, (unsigned) 7, (unsigned) 7, (unsigned) 7);"-line everything is fine, all 4 output positions give me the (7,7,7,7). Without only on position 1 and 4 I get the right result (input is (2,0,0,0) and output (4,0,0,0), on position 4 just zeros are returned and on position 3 (4, 0, 3ee8e8e9, 3f800000) or (4, 0, 3ee6e6e7, 3f800000) is returned. output stream doesn't report any error ....

 

0 Likes

Please post your code.

0 Likes

Ok, complete code for this subkernel is here:

http://pastebin.com/m19916be2

The error occurs in the function "multMod" (the function at the bottom of the code). The function tries to multiply two 124 bit integers modulo a given 124 bit modulus.

One 124 bit number is represented by one uint4 value with the highest bit of every subuint leaved out, because with this modification overflow-handling is easier.

The pure mult-function is split into 3 parts (low, mid and high), becaus return of one single function would be a uint8 - not possible in brook+, so i split this function into 3 parts.

The callable function isn't posted in that code-link, but is just taking one input stream and one constant modulus, caling the subkernel in the way outputStream = multMod(input1, input1, modulus,0);

Thanks for the time you invest to help

 

0 Likes

Subkernel multiplyUInt31 in missing.  Please supply.

0 Likes

Oh, I'm sorry, here it is:

http://pastebin.com/m42e17a1

Ps: the term const uint highBit = ((unsigned) 2147483646) + (unsigned) 2; is a bugfix, because 0x80000000 or decimal 2147483648 isn't realy working as constant... whyever...

0 Likes

Three more missing pieces: subUint124Modulo, shiftUint124Left and shiftUint124Right.

0 Likes

Ok, here is the rest of the code used,

http://pastebin.com/m440936fd

I am sorry for being so forgetful...

0 Likes

OK, after a bit of work...

Your problem actually has nothing to do with multMod but is further upstream, in functions such as multiplyUInt124Mid, etc.

For example, in multiplyUInt124Mid, you use tmpRes as an accumulator, but you initialize tmpRes.xy only, which of course leaves tmpRes.z and tmpRes.w undefined. 

Brook does not automatically initialize your variables to 0.  Because the content of that memory location changes everytime you run the program (and also depending on the order of the instructions), the results are unpredictable.  This initialization problem is hard to debug, because the results appears to be partially right sometimes; but in fact, it was never right.

0 Likes

Thank you very, very much!

There are still some flews in my code, but now most things work like they should.

0 Likes