2

There are two large matrices in my code, which have the same number of columns and different number of rows. Like A(20000X4000) and B(30000X4000). Both are 0-1 sparse.

I should check each row of A with all rows of B and count the number of common 1s. For example if A(1,:)=[0 1 0 1 1] and B([1 2],:)=[1 1 1 1 1;0 0 0 1 1], I need to get the result as 3 and 2.

Assume there is a large 0-1 matrix C(50000X4000) and its rows are labeled as either type A or type B. I should compare all rows of A and B together and enumerate 1s. If the number of 1s in each row of A and B are greater than some bounds, then I used those rows of A and B for the rest of calculation. So, I do not even need to store A and B, all I need is a list of pairs of indices of rows. Something like [(3,2),(3,5),...] which shows I should use the third row of A and the second row of B, also the third of A and the fifth of B and so on.

The first thing that came into my mind was A*B', it gives the correct result, but practically it is very costly and in some cases impossible to do this multiplication.

I converted the matrices into single data type, and it became a bit faster. Sparse did not help.

The task seems easy, just counting common 1s of each row of A and all rows of B, but not easy to implement. Considering that the code should do this task like 1000 times, then it is practically impossible.

Any idea how to do enumerate the common ones without multiplication? (btw, loops also did not help).

Thanks.

Alef
  • 41
  • 1
  • 7
  • how sparse are the matrices, i.e. roughly how many ones? – A. Donda Dec 09 '13 at 20:09
  • In general one cannot improve on `A*B'`. And even switching to C++ will likely not give a significant improvement. So, the only hope you may have is to 1. Solve the problem differently, or 2. use more helpfull information. The fact that it is a logical matrix is this kind of information, but unfortunately it is not enough. You can ask yourself, how sparse are the matrices, do they have a specific structure? How sparse is your outcome matrix? – Dennis Jaheruddin Dec 09 '13 at 20:10
  • in any case, the result will be a 20000 x 30000 matrix. do you really need this matrix? what do you plan to do with it when you have it? – A. Donda Dec 09 '13 at 20:11
  • Actually I do not need these matrices, I want to enumerate the common factors between two matrices. Like assume there is a large 0-1 matrix C(50000X4000) and its rows are labeled as either type A or type B. I should compare all rows of A and B together and enumerate 1s. If the number of 1s in each row of A and B are greater than some bounds, then I used those rows of A and B for the rest of calculation. – Alef Dec 10 '13 at 05:53
  • @Alef, I think it would really help your chances to get a useful answer, if you would edit your question to include this information, and explain it in more detail than here in the comment. Maybe there's a way to reach your goal without this computation. – A. Donda Dec 10 '13 at 19:00
  • did anything more come out of this? – MZimmerman6 Dec 17 '13 at 16:09
  • @MZimmerman6 Actually no. I have not found any good technique for this enumeration task that be faster than the multiplication. I am still trying though. – Alef Dec 17 '13 at 18:02
  • I still honestly do not think you will get anything more. Matrix multiplication is going to have the same complexity. With one `n x m` and one `m x p`, you complexity is `O(n*m*p)` or essentially the same complexity of the method I proposed. Also, the direct bit-wise comparison I am doing is much faster than multiplication. To see this, simply change `@eq` to `@times` inside the for loop – MZimmerman6 Dec 17 '13 at 18:47
  • you may be able to get away with speeding stuff up by using CUDA, but you had stated below under my answer that you are using a laptop with only 4GB RAM, that likely does not have a CUDA capable NVidia GPU. If you can get a hold of one, possibly rent or find someone who will let you borrow it, you may be able to do this computation in few minutes, but I am not sure. – MZimmerman6 Dec 17 '13 at 18:59

4 Answers4

2

I do not know if this is really any better than what you have, because it does still have a for loop in it, but if someone can figure out how to remove that for loop you should be good to go.

%  create temp data
A = rand(20000,4000) < 0.5;
B = rand(30000,4000) < 0.5;
counts = zeros(size(A,1),size(B,1),'uint8');
for i = 1:size(A,1)
    counts(i,:) = sum(bsxfun(@eq,A(i,:),B),2);
end

Either way, the process is going to take a long time because you are comparing 30000 rows with 4000 elements each, 20000 times, or approximately 2.4e+12 comparisons. That is a huge task, and will definitely take a long time. Possibly try using parallel computing if you need it to be faster.

MZimmerman6
  • 8,445
  • 10
  • 40
  • 70
  • Thanks! However the sizes of matrices do not allow any loops; it gets more time consuming and I cannot run the code. – Alef Dec 07 '13 at 17:32
  • @Alef I am not sure you understand the fact that either way this is going to be a huge comparison. requiring at least 30000*4000*20000 = 2.4e12 comparisons. That is massive. And even though you may be able to "optimize" it, that same number of comparisons will need to happen – MZimmerman6 Dec 09 '13 at 14:22
  • That is correct, and that is why I am stuck. I have been trying to reframe the problem, or reformulate it, and still have no progress. My main concern here is that, I was thinking there might be some enumeration methods that can be applied on this specific problems (0-1 matrices) that I am not aware of. – Alef Dec 09 '13 at 18:41
  • I really do not think there is any simple way out of this. Sorry. I mean it will run, it will just take a while. If you are really impatient, or are having RAM issues, you can break the matrices up into smaller chunks – MZimmerman6 Dec 09 '13 at 19:21
  • Running this program on my laptop which only has an Intel i5 CPU takes approximately an hour. But once it completes, you can save the results, and never have to run the program again. Or you can always speed up the process by using parfor and the parallel computing toolbox – MZimmerman6 Dec 09 '13 at 19:51
  • How come parallel computing does not improve this multiplication on my laptop? Usually it assigns 2 workers, and there is no improvement. The machine is an HP EliteBook 2560p, 4GB ram. – Alef Dec 10 '13 at 05:45
  • I don't know what to tell you there. The one issue I do see is that you only have 4GB of RAM, I would recommend making the counts matrix uint8 by simply changing its initialization to `zeros(size(A,1),size(B,1),'uint8')` – MZimmerman6 Dec 10 '13 at 15:24
1

I did some benchmarking; on my machine (i7-3770 @ 3.40GHz), multiplying full matrices of size 30000 x 4000 and 4000 x 20000 takes about 55 seconds regardless of content, the same that Dennis Jaheruddin found. But using sparse matrices can make the computation faster, depending on sparseness. If I define the degree of sparseness r as the ratio between the number of 1s to elements of the matrix, I get the following results:

r      time / s 
0.001   0.07
0.002   0.3
0.005   2.1
0.01    8.3
0.02   25

Here is the code used to determine these numbers:

m = 20000;
n = 4000;
o = 30000;

r = 0.001;

N = round(r * m * n);
A = sparse(randi(m, N, 1), randi(n, N, 1), 1, m, n);

N = round(r * n * o);
B = sparse(randi(o, N, 1), randi(n, N, 1), 1, o, n);

tic
C = A * B';
toc
A. Donda
  • 8,381
  • 2
  • 20
  • 49
  • This is correct, MatLab/Octave does not compute the 0s (you even have a special function spfun() to make your own custom sparse function!). I think it can even skip whole columns altogether since it knows if the column is totally empty or not. I currently use sparse matrices for a project using huge matrices, and it indeed lowers down the CPU time wrt the network's density (number of 1's = r degree of sparseness of Donda). – gaborous Jun 16 '14 at 13:27
0

If multiplication of the whole matrices cannot be done, one idea is to process a vertical stripe at a time. For each stripe you compute the desired result, and accumulate it with that of the preceding stripes:

A = double(rand(5,300)<.5); %// random data
B = double(rand(4,300)<.5); %// random data

S = 10; %// stripe size
result = zeros(size(A,1),size(B,1)); %// initialize to 0
for s = 1:10:size(A,2) %// each vertical stripe, of width S
    ind = s+(0:S-1);
    result = result +  A(:,ind)*(B(:,ind)).';
end

Check:

>> result

result =

    73    72    62    72
    84    70    79    71
    83    84    76    77
    77    80    77    74
    71    71    70    74

>> A*B.'

ans =

    73    72    62    72
    84    70    79    71
    83    84    76    77
    77    80    77    74
    71    71    70    74
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Thanks for the suggestion, but it does not work for my case! This issue is so irritating for me now. – Alef Dec 07 '13 at 17:33
  • I meant it takes much more time than what I can get from regular matrix multiplication in Matlab. The approach is correct of course, but does not help in speed. Thanks man! – Alef Dec 10 '13 at 05:34
0

The solution that you tried is optimal or near optimal.

When I try this, it takes less than a minute:

A = round(rand(30000,4000));
B = round(rand(20000,4000));
tic,A*B';toc;

If you really need to do this thousands of times, there are only two scenarios that I can imagine:

  1. You don't need to do it often, in that case just let it run and it will be done tomorrow
  2. You want to do it often and speed matters, finding a much faster solution is simply not going to happen. Unless you have some very usefull information about the matrices that you will be multiplying.

If you find that this sample multiplication much more than a minute (say more than 10 minutes), you probably are using memory inefficiently. In that case try to get some more ram.

Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
  • I should use this enumeration in an algorithm, which should be used by "everyone" (people in my target group), so it is not a data analysis project, it is more an algorithm development task. I wish it was just for one time running, then I could use/rent a computation service from IT service at the university and do everything in a reasonable time. Thanks! – Alef Dec 10 '13 at 05:39