opened
sroboubi
username_0
I'm trying to get a histogram of some data, and in general this is a serial operation but I can split the input into chunks and calculate the histogram of each chunk in parallel then add them all up. To do this I need to be able to output an array from a kernel function. Something like this (which clearly doesn't work):

```
        var size = 10;
        var input = new Uint8Array(size*size);
        for (var i = 0; i < input.length; i++) {input[i] = i;}

        var kernel = gpu.createKernel(function(input, size)
        {
            var result = new Array(size);   // this wont work
            for (var i = 0; i < size; i++)
            {
                var idx = input[i+(size*this.thread.x)];
                result[idx]++;
            }
            return result;
        }).setOutput([size]);

        // output should be array of arrays: [[...][...][...]...]
        var output = kernel(input, size);
```

Is there any way to do this?
Output arrays instead of individual values from kernel
issue
created
robertleeplummerjr
username_1
What is the histogram of?
comment
created
sroboubi
username_0
In a real application it would probably be the histogram of some image data. In the example code above it is the histogram of the _input_ array. 
Perhaps there is no way to do this because there might be no way to output an array from a kernel functions. I assume it is a per pixel (or per array element) operation which expects the output to be a single value in the output array.
comment
created
nickhingston
username_2
yes this is possible, you need a 2d output array

.setOutput([size, size])

then If i understand correctly use thread.y instead of your loop

`var idx = input[this.thread.x +(size*this.thread.y)];`
comment
created
robertleeplummerjr
username_1
@username_2 is correct.  In gpu.js, think of the kernel _as the loop_.
comment
created
sroboubi
username_0
I don't see how this would work. Remember that this is a histogram, so the idx you're calculating here
`var idx = input[this.thread.x +(size*this.thread.y)];`
is actually an index into the output array. If I'm missing something please show me the updated code (using a 2d output array). Thanks.
comment
created
robertleeplummerjr
username_1
What does your input look like?

When using gpu.js, the source _looks like javascript but it actually calculates the index for you on the fly and applies it to the inputs_.  If you are using a 1d array that is a flattened 2d array (which is recommended for performance), you can also _interact with it as 2d_ by using `GPU.input` mentioned here: https://github.com/gpujs/gpu.js#flattened-typed-array-support
comment
created
sroboubi
username_0
The input would probably be some imagery/raster data. But I don't think it matters, you can refer to the example code I posted above... if there is some way to make that example work I would be pleasantly surprised.
comment
created
nickhingston
username_2
@username_0 ok, I think I get you

so if you had example input (for size = 4):
`[[1,2,2,3], [3,3,3,1], [0,0,0,0]]`
output:
`[[0,1,2,1], [0,1,0,3], [4,0,0,0]];`

think it should be possible by combining kernels...not worked it out yet, but want to make sure my understanding of your problem is correct?

if this is right your example was somewhat confusing with:
```
var input = new Uint8Array(size*size);
for (var i = 0; i < input.length; i++) {input[i] = i;}

```
as input[i] should only ever be a max of (size-1)
comment
created
sroboubi
username_0
@username_2 
Yes your understanding is correct. My example wasn't meant to be representative of real data and, as you mentioned, the input array values would end up being a bit confusing. I was just trying to demonstrate the functionality that I was looking for.
From my limited understanding, this might not be possible with shaders (and therefor with GPU.js), however if you find a way that would be great. For more information you can refer to https://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/histogram64/doc/histogram.pdf. Specifically the first half-page under the "Motivation" sub-section basically describes the problem and potential solution.
comment
created
nickhingston
username_2
ok, this works.  Though I certainly wont guarantee it is faster than a well optimised CPU version!
```

var gpu = new GPU({ mode });
		
		function countIndex(idx, size, input) {
			var count = 0;
			for (var i = 0; i < size; i++) {
				if (idx == input[this.thread.y][i]) {
					count++;
				}
			}
			return count;
		}

		gpu.addFunction(countIndex);

		var histogramKernel = gpu.createKernel(function(input, size)
		{	
			return countIndex(this.thread.x, size, input);
		}).setOutput([size, size]);
		
		return histogramKernel(input, size);
```
comment
created
nickhingston
username_2
It should be possible to optimise this when #346 is done (would need 2 input arrays,  Closing this task.
comment
closed
nickhingston
username_2
issue