Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
histc for gpu

Subject: histc for gpu

From: Christian

Date: 25 Jan, 2014 21:28:07

Message: 1 of 7

Hi,

I hope to use histc on CUDA, but it's not a supported function. So I tried a workaround because I'm actually just interested in the second output argument:

[~,ind] = histc(x,x_grid);

is more or less equivalent to the following code (except for points outside the grid).

ind=ones(size(x));
for j=1:length(x_grid)-1
    ind(x>=x_grid(j) & x<x_grid(j+1)) = j;
end

But this latter code is much slower than histc, probably due to the loop. For instance, for my inputs the first code requires 0.03 seconds, the latter needs 1.8 seconds.

Is it possible to speed up the second code so that I can still run it on CUDA?

Thanks,
Christian

Subject: histc for gpu

From: Edric M Ellis

Date: 27 Jan, 2014 10:06:54

Message: 2 of 7

"Christian " <proechri@umich.edu> writes:

> Path: news.mathworks.com!not-for-mail
> Newsgroups: comp.soft-sys.matlab
> Subject: histc for gpu
> Date: Sat, 25 Jan 2014 21:28:07 +0000 (UTC)
> Organization: The MathWorks, Inc.
>
> Hi,
>
> I hope to use histc on CUDA, but it's not a supported function. So I tried a workaround because I'm actually just interested in the second output argument:
>
> [~,ind] = histc(x,x_grid);
>
> is more or less equivalent to the following code (except for points outside the grid).
>
> ind=ones(size(x));
> for j=1:length(x_grid)-1
> ind(x>=x_grid(j) & x<x_grid(j+1)) = j;
> end
>
> But this latter code is much slower than histc, probably due to the loop. For instance, for my inputs the first code requires 0.03 seconds, the latter needs 1.8 seconds.
>
> Is it possible to speed up the second code so that I can still run it
> on CUDA?

I haven't profiled this, but you can run just the binning part of HISTC
on the GPU using arrayfun and up-level variables to access the bins:

%%%%%%%%%%%%%%%%%%%%
function test()

% Test inputs
q = gpuArray.randi([1 10], 1, 1000);
edges = 1:8;

% Implementation
nEdges = numel(edges);
    function b = bindata(x)
        b = 0;
        if x == edges(nEdges)
            b = nEdges;
        else
            for idx = 1:(nEdges-1)
                if x >= edges(idx) && x < edges(idx + 1)
                    b = idx;
                    break;
                end
            end
        end
    end
b = arrayfun(@bindata, q);

% Check against the CPU
[~, bcheck] = histc(gather(q), edges);
assert(isequal(b, bcheck));
end
%%%%%%%%%%%%%%%%%%%%

Cheers,

Edric.

Subject: histc for gpu

From: Christian

Date: 15 Feb, 2014 14:39:07

Message: 3 of 7

Edric M Ellis <eellis@mathworks.com> wrote in message <ytwmwihkabl.fsf@uk-eellis0l.dhcp.mathworks.com>...
> "Christian " <proechri@umich.edu> writes:
>
> > Path: news.mathworks.com!not-for-mail
> > Newsgroups: comp.soft-sys.matlab
> > Subject: histc for gpu
> > Date: Sat, 25 Jan 2014 21:28:07 +0000 (UTC)
> > Organization: The MathWorks, Inc.
> >
> > Hi,
> >
> > I hope to use histc on CUDA, but it's not a supported function. So I tried a workaround because I'm actually just interested in the second output argument:
> >
> > [~,ind] = histc(x,x_grid);
> >
> > is more or less equivalent to the following code (except for points outside the grid).
> >
> > ind=ones(size(x));
> > for j=1:length(x_grid)-1
> > ind(x>=x_grid(j) & x<x_grid(j+1)) = j;
> > end
> >
> > But this latter code is much slower than histc, probably due to the loop. For instance, for my inputs the first code requires 0.03 seconds, the latter needs 1.8 seconds.
> >
> > Is it possible to speed up the second code so that I can still run it
> > on CUDA?
>
> I haven't profiled this, but you can run just the binning part of HISTC
> on the GPU using arrayfun and up-level variables to access the bins:
>
> %%%%%%%%%%%%%%%%%%%%
> function test()
>
> % Test inputs
> q = gpuArray.randi([1 10], 1, 1000);
> edges = 1:8;
>
> % Implementation
> nEdges = numel(edges);
> function b = bindata(x)
> b = 0;
> if x == edges(nEdges)
> b = nEdges;
> else
> for idx = 1:(nEdges-1)
> if x >= edges(idx) && x < edges(idx + 1)
> b = idx;
> break;
> end
> end
> end
> end
> b = arrayfun(@bindata, q);
>
> % Check against the CPU
> [~, bcheck] = histc(gather(q), edges);
> assert(isequal(b, bcheck));
> end
> %%%%%%%%%%%%%%%%%%%%
>
> Cheers,
>
> Edric.

Thanks, Edric. I have some trouble getting your code running. I've set up a function file:

    function b = bindata(x,edges)
        nEdges = 100;
        b = 0;
        if x == edges(end)
            b = nEdges;
        else
            for idx = 1:(nEdges-1)
                if x >= edges(idx) && x < edges(idx + 1)
                    b = idx;
                    break;
                end
            end
        end
    end

I changed nEdges=numel(edges) to just the size of edges because the arrayfun command didn't like numel. But still when running the code from my main file using

indx = arrayfun(@bindata, xpgpu, x_gridgpu);

I receive the message
Error using gpuArray/arrayfun
Indexing is not supported.
for lines 4 and 8.

Thanks for your help,
Christian

Subject: histc for gpu

From: Edric M Ellis

Date: 20 Feb, 2014 07:56:02

Message: 4 of 7

"Christian " <proechri@umich.edu> writes:

>> [...]
>
> Thanks, Edric. I have some trouble getting your code running. I've set up a function file:
>
> function b = bindata(x,edges)
> nEdges = 100;
> b = 0;
> if x == edges(end)
> b = nEdges;
> else
> for idx = 1:(nEdges-1)
> if x >= edges(idx) && x < edges(idx + 1)
> b = idx;
> break;
> end
> end
> end
> end
>
> I changed nEdges=numel(edges) to just the size of edges because the
> arrayfun command didn't like numel. But still when running the code
> from my main file using
>
> indx = arrayfun(@bindata, xpgpu, x_gridgpu);
>
> I receive the message
> Error using gpuArray/arrayfun
> Indexing is not supported.
> for lines 4 and 8.

Which version of MATLAB/PCT are you using? You need at least R2013a to
use indexing within ARRAYFUN. See

http://www.mathworks.co.uk/help/distcomp/release-notes.html

Cheers,

Edric.

Subject: histc for gpu

From: Bruno Luong

Date: 20 Feb, 2014 13:39:09

Message: 5 of 7

"Christian " <proechri@umich.edu> wrote in message <lc1a97$6tt$1@newscl01ah.mathworks.com>...
> Hi,
>
> I hope to use histc on CUDA, but it's not a supported function. So I tried a workaround because I'm actually just interested in the second output argument:
>
> [~,ind] = histc(x,x_grid);
>
> is more or less equivalent to the following code (except for points outside the grid).
>
> ind=ones(size(x));
> for j=1:length(x_grid)-1
> ind(x>=x_grid(j) & x<x_grid(j+1)) = j;
> end
>
 
The best way is perhaps to sort x and x_grid concatenated together, which has an O(N*log(N)) complexity where N is numel(x)+ numel(xgrid). Furthermore the histc engine is possibly programmed in C and very optimal way.

You won't beat it with the trivial for-loop, even with CUDA.

Bruno

Subject: histc for gpu

From: Christian

Date: 7 Mar, 2014 14:44:12

Message: 6 of 7

Hi Edric,

I'm using Matlab 2013b, so not sure why it doesn't work. I just discovered another part of my algorithm that could benefit from histc. So having a gpu version of it would be great.
Christian

Edric M Ellis <eellis@mathworks.com> wrote in message <ytweh2y9q0d.fsf@uk-eellis-deb7-64.dhcp.mathworks.com>...
> "Christian " <proechri@umich.edu> writes:
>
> >> [...]
> >
> > Thanks, Edric. I have some trouble getting your code running. I've set up a function file:
> >
> > function b = bindata(x,edges)
> > nEdges = 100;
> > b = 0;
> > if x == edges(end)
> > b = nEdges;
> > else
> > for idx = 1:(nEdges-1)
> > if x >= edges(idx) && x < edges(idx + 1)
> > b = idx;
> > break;
> > end
> > end
> > end
> > end
> >
> > I changed nEdges=numel(edges) to just the size of edges because the
> > arrayfun command didn't like numel. But still when running the code
> > from my main file using
> >
> > indx = arrayfun(@bindata, xpgpu, x_gridgpu);
> >
> > I receive the message
> > Error using gpuArray/arrayfun
> > Indexing is not supported.
> > for lines 4 and 8.
>
> Which version of MATLAB/PCT are you using? You need at least R2013a to
> use indexing within ARRAYFUN. See
>
> http://www.mathworks.co.uk/help/distcomp/release-notes.html
>
> Cheers,
>
> Edric.

Subject: histc for gpu

From: Edric M Ellis

Date: 7 Mar, 2014 16:40:19

Message: 7 of 7

"Christian " <proechri@umich.edu> writes:

> I'm using Matlab 2013b, so not sure why it doesn't work. I just discovered
> another part of my algorithm that could benefit from histc. So having a gpu
> version of it would be great.

Hi Christian,

It's crucial that your 'bindata' function is a nested function inside
your main function. You can only index into "up-level" variables - this
is the only way that you can access the whole value of an array from
within your arrayfun function. If you look back at my original posting,
that's what I did.

Cheers,

Edric.

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us