Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is there a "parallel" way to perform these operations?

Indices = {}
For[i = 1, i <= Length[w], i++,
 If[w[[i]] < 0, AppendTo[Indices, i]]]

Which gives a list of the Indices where the list w is negative. This is a little slow.

Is there a faster cleaner way to get the same answer? This is essentially the Fortran 90 where statement.

share|improve this question
1  
indices = Select[w, Negative] -- not parallel, but reasonably efficient. Or Pick[w, Negative[w]]. –  Michael E2 Mar 14 at 15:54
2  
If you need the indices, not the elements, use Position[w, _?Negative]. Parallelization is not the best or fastest approach for this task in Mathematica. –  Szabolcs Mar 14 at 16:25
    
Thanks Szabolcs. "Position" is what I needed. I was using "parallel" loosely, as in what was once upon a time called "SIMD" (single instructions multiple data). –  JEP Mar 14 at 17:06
    
@JEP In that case, for good performance, you can try Pick[Range@Length[w], UnitStep[w], 0]. I think this will be the fastest way to get the indices (but depending what you want to do afterwards, using the indices may not be the fastest solution). –  Szabolcs Mar 14 at 22:52

3 Answers 3

I suppose it's better to make my comment into an answer, per SE policy. The slowness is due to AppendTo, which has been pointed out by many others before, as well as in the documentation.

To get the indices,

indices = Pick[Range[Length[w]], UnitStep[w]]

will be fast.

Reasons for starting variable names with a lower-case letter instead of a capital have been discussed before, too.


Original answer

[I misread what was being stored. Oops.]

Two possibilities:

indices = Select[w, Negative]

indices = Pick[w, Negative[w]]

Pick will be faster on large packed arrays. Or as Szabolcs points out, it will be even faster if both arguments are packed:

indices = Pick[w, UnitStep[w]]
share|improve this answer
1  
Actually Pick will be fastest if both arguments are packed, i.e. Pick[w, UnitStep[w], 0]. –  Szabolcs Mar 14 at 16:27
    
Thanks to both. –  JEP Mar 14 at 16:37

Just for comparison: Consider following approaches:

f[x_] := Cases[x, _?Negative];
g[x_] := Select[x, Negative];
h[x_] := Pick[x, UnitStep[x], 0];
k[x_?Negative] := x;
k[x_] := Sequence[];

Testing on:

list = RandomReal[{-1, 1}, 10^6];

yields:

enter image description here

share|improve this answer

Based on @Szabolcs, we could parallelize by partitioning the list and using ParallelMap. Assuming $KernelCount is not zero,

Data:

w = RandomReal[{-1, 1}, Prime[10^6]];

Without parallelizing:

First@Timing[a1 = Flatten@Position[w, _?Negative];]

17.097710

Parallelizing:

First@Timing[
  a2 = With[
     {
      n = Quotient[Length[w], $KernelCount]
      },
     Flatten[
      Range[0, Length[w], n]
       + ParallelMap[Flatten[Position[#, _?Negative]] &, 
        Partition[w, n, n, 1, {}]]
      ]
     ];]

7.441248

a1 == a2

True

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.