Performance-wise, it wouldn't make sense because the overhead is much larger when evaluating it on 4 cores. Please look at the settings of Method
in Parallelize
and apply it to your ParallelDo
ParallelDo[
Print["i=" <> ToString[i] <> "; " <> "j=" <> ToString[j]], {i, 1,
10}, {j, 1, 10}, Method -> "FinestGrained"]
This uses all 8 cores I have available, but remember that finding the right chunk-size is important to optimize speed. Distributing a computation on all cores is not always the best choice.
If you want a deeper insight, you can look at the output of the following
ParallelTable[
$KernelID, {i, 1, 10}, {j, 1, 10},
Method -> "FinestGrained"] // Column
(*
{8,8,8,8,8,8,8,8,8,8}
{7,7,7,7,7,7,7,7,7,7}
{6,6,6,6,6,6,6,6,6,6}
{5,5,5,5,5,5,5,5,5,5}
{4,4,4,4,4,4,4,4,4,4}
{3,3,3,3,3,3,3,3,3,3}
{2,2,2,2,2,2,2,2,2,2}
{1,1,1,1,1,1,1,1,1,1}
{8,8,8,8,8,8,8,8,8,8}
{7,7,7,7,7,7,7,7,7,7}
*)
That seems to indicate that your outer iteration needs to be at least 32 to use all cores.
Edit
If you know what you are doing (because finding the sweet-spot in parallelization is not always trivial), you can parallelize to whatever level you like. One solution is to use only a 1-dim loop and recover the indices inside the loop. Here is an example that is equivalent of {i,1,4}
and {j,1,4}
but doing every element in parallel:
ParallelDo[Print[{QuotientRemainder[x, 4] + 1, $KernelID}], {x, 0, 7}]

It uses all 8 kernels I have. If you have a more complex iterator pattern, you can create the iterators upfront
iter = Flatten[Table[{i, j, k}, {i, 3}, {j, 4}, {k, 5}], 2];
ParallelDo[Print[{it, $KernelID}], {it, iter}]
Again, each element is processed in parallel.
{i,1,2},{j,1,8}
only two subkernels are used, but when you use{j,1,8},{i,1,2}
all 4 subkernels are used. $\endgroup$ – Fred Simons May 27 '18 at 14:00