Closed balazsmolnar72 closed 3 years ago
<meta charset="utf-8">
<script src="dist/gpu-browser.min.js"></script>
<script>
noSamples=100;
const gpu = new GPU();
const kernel = gpu.createKernel(function() {
function isDuplicate(numOfDigits, digit){
let num=0; // realized that cannot make a definition and an assignment in the same line
num=numOfDigits;
while(num>0){
if(num%10==digit){
return 1;
}
num=Math.floor(num/10);
}
return 0;
}
function generateSample(numDigits){
let number=0;
let nextDigit=0;
for(let i=0;i<numDigits;++i){
while(1>0){ // true simple true condition does not work
nextDigit=Math.floor(Math.random()*9);
if(isDuplicate(number, nextDigit)==0){
number*=10;
number+=nextDigit;
break;
}
}
}
return number;
}
return generateSample(7);
}).setOutput([100]);
let samplesArray=kernel();
for(let i=0;i<noSamples;++i){
document.write(samplesArray[i].toString()+"<br>");
}
</script>
Hmm I did some testing and doing a bitwise OR seemed to fix the issue.
Change number+=nextDigit;
to number += nextDigit | 0;
fixed the issue. Bitwise operators are defined to work only on ints, so doing someNumber | 0
casts that to an int. It's weird that Math.floor
didn't seem to work,
It looks like in the generated kernel, the compiler infers that your type is a float. But somehow floor doesn't work.
float generateSample(float user_numDigits) {
float user_number=0.0;
float user_nextDigit=0.0;
int user_i=0;
for (int safeI2=0;safeI2<LOOP_MAX;safeI2++){
if (!(user_i<int(user_numDigits))) break;
for (int safeI=0;safeI<LOOP_MAX;safeI++){
if (!(1.0>0.0)) break;
{
user_nextDigit=floor((nrand(vTexCoord)*9.0));if ((isDuplicate(user_number, user_nextDigit)==0.0)){
user_number*=10.0;user_number=user_number;user_number+=user_nextDigit;break;}
}
}
++user_i;}
return user_number;
}
This is the generated kernel with the OR hack.
float generateSample(float user_numDigits) {
float user_number=0.0;
float user_nextDigit=0.0;
int user_i=0;
for (int safeI2=0;safeI2<LOOP_MAX;safeI2++){
if (!(user_i<int(user_numDigits))) break;
for (int safeI=0;safeI<LOOP_MAX;safeI++){
if (!(1.0>0.0)) break;
{
user_nextDigit=floor((nrand(vTexCoord)*9.0));if ((isDuplicate(user_number, user_nextDigit)==0.0)){
user_number*=10.0;user_number=user_number;user_number+=float(bitwiseOr(int(user_nextDigit),0));break;}
}
}
++user_i;}
return user_number;
}
The difference appears to be that the int()
function is called when we have the OR hack. I did notice that in the generated kernel, there is no definition for the floor function. Is that expected behavior?
Thanks! I can confirm that the issue with the floating number is eliminated by the OR hack. Thank you!
But even better if I put the OR hack to the line when the random number is generated.
nextDigit=Math.floor(Math.random()*9) |0;
Since I would like to use this number not only in the addition, but also as an argument of a function, where the float also causes problems. Maybe I can leave out the Math.floor() since it does not work anyway. Thanks for your hint again!
No problem! Glad to help!
What is wrong?
I wanted to create a random number generator, which generates 6 digit random numbers where a number can be only at a single place. It executes perfectly in Javascript, but when I create a kernel it starts to behave strangely. When I evaluated a condition in an if statement it added unwanted decimals to one of the variables.
Where does it happen?
GPU.js running in a Chrome Browser on a Windows 10 machine
How do we replicate the issue?
Run the code in a Chrome Browser. It always produces the issue.
How important is this (1-5)?
3
Expected behavior (i.e. solution)
Evaluating an if condition should not alter the variables.
Other Comments
The debugging possibilities described in the documentation does not work in these environment. When I add { mode: 'dev'} as a parameter to new GPU() statement It gives an error message when I try to call the kernel: Uncaught TypeError: kernel is not a function