in reply to Can this code be optimized further?

I wouldn't use push. If @temp is large (which assume it is, if it isn't there's no need to bother with optimizing it), repeated pushes means repeated mallocing the array needed for @a and @b as it extends.

I'd use:

my @temp = (...); my @a = map {/a_(.*)/ ? $1 : ()} @temp; my @b = map {/b_(.*)/ ? $1 : ()} @temp;
If you expect to not have many matches, that is, most elements in @temp don't contain a_ or b_, I'd try to see whether the simpler regex is enough gain to have both the map and the grep:
my @a = map {/a_(.*)/; $1} grep /a_/ @temp; my @b = map {/b_(.*)/; $1} grep /b_/ @temp;