Consider the following two lists:
listtest = {11, 13, 22, 221, 1, 3} // Sort // N;
pdglisttest = RandomInteger[{-222, 222}, 10^6] // N;
For the given element of pdglisttest
, I want to return 1 if it belongs to listtest
and 0 otherwise. In the real case, listtest
and pdgtest
are not fixed, and this operation is just a sub-action required when calculating some quantity.
I make two codes - one using MemberQ
and another one without it, by using explicit If
:
comp = Compile[{{list, _Real, 1}, {pdglist, _Real}},
If[MemberQ[list, Abs[pdglist]], 1, 0], CompilationTarget -> "C",
RuntimeAttributes -> {Listable}, RuntimeOptions -> "Speed"]
comp1 = Compile[{{pdglist, _Real}},
Module[{pdg},
pdg = Abs[pdglist];
If[pdg == 1. || pdg == 3. || pdg == 11. || pdg == 13. ||
pdg == 22. || pdg == 221., 1, 0]
], CompilationTarget -> "C", RuntimeAttributes -> {Listable},
RuntimeOptions -> "Speed"]
It turns out that the one with MemberQ
is triple as slow:
t=comp[listtest, pdglisttest]; // AbsoluteTiming
t1=comp1[pdglisttest]; // AbsoluteTiming
t==t1
{0.0855261,Null}
{0.0257923,Null}
True
However, MemberQ
is very convenient and probably unavoidable if pdglist
is not fixed. Is it possible to speed it up, or the slowdown cannot be handled?
Edit
Adding the option Parallelization->True
to both codes reduces the timing difference down to a factor of 1.5-2, but it is still present.
listtest
and run a binary search. Should be the same algorithm as inMemberQ
(but compilable). $\endgroup$