4

When using a function that includes Print statements, one can suppress the output by

Print; Unprotect[Print]; Print = Null &

This doesn't work when the function is evaluated in

ParallelTable[function[i],{i,1,10}]

Is there a way to do that? Thank you!

user13655
  • 377
  • 1
  • 8

3 Answers3

7

You can use dynamic scoping, i.e. the Block construct, to temporarily "forget" or redefine Print.

ParallelTable[
Block[{Print},
Print; Unprotect[Print]; Print = Null &
function[x],
{x,0,10}
]

This works with ParallelTable for me.

kadrach
  • 560
  • 1
  • 3
  • 10
  • works! thank you. – user13655 May 02 '12 at 10:47
  • What about Block[{Print = Null&}, ...]? That doesn't even need an Unprotect. – celtschk May 02 '12 at 11:04
  • 3
    I would find it unusual if this worked, because the definition of Print is not synchronized across kernels, and indeed it does not work here. I tried Block[{}, Print; Unprotect[Print]; Print = Null &; ParallelDo[Print[i], {i, 1, 10}]] which is completely analogous with your example, yet it does print the output. Furthermore, in your example the modification of Print is not temporary. – Szabolcs May 02 '12 at 11:30
  • As I said, it works for me. Including temporary modification. Why it works, may be a different question. – kadrach May 02 '12 at 11:45
  • 1
    @noe Try in a fresh kernel. If you use the exact same code that you posted, the modification cannot be temporary, because you didn't pass Print to Block in the first argument. Then there's the question of synchronization between subkernels. – Szabolcs May 02 '12 at 11:47
  • 1
    The only way I can see this working is if you put this code inside ParallelTable, but even then you will change the definition of Print permanently for the parallel kernels. Try for example running ParallelDo[Print[i], {i,10}] afterwards. A safer option would be to do something like ParallelTable[Block[{Print}, Print = Null &;...], ...]. – Heike May 02 '12 at 12:31
  • I'm sorry if I was unclear, but I did indeed put the Block within ParallelTable, i.e. ran ParallelTable[Block[..]]. – kadrach May 02 '12 at 12:59
  • 1
    @noe If you put the Block inside ParallelTable then in fact Block had no effect. Dynamic scoping was not used. What happens is that Print is redefined permanently in all the subkernels, but not in the main kernel. – Szabolcs May 02 '12 at 13:20
7

Use

ParallelDo[Block[{Print = Null&}, Print[{i, $KernelID}]], {i,1,10}]

You can also make it into a function:

SetAttributes[ParallelDoSilent, HoldAll]
ParallelDoSilent[expr_, iter_] :=
  ParallelDo[Block[{Print = Null&}, expr], iter]

ParallelDoSilent[Print[{i, $KernelID}], {i,1,10}]
celtschk
  • 19,133
  • 1
  • 51
  • 106
  • 2
    +1, yes, this is the correct and general solution. This is good reading on Block (for the OP): http://stackoverflow.com/questions/6661393/mathematica-module-versus-with-or-block-guideline-rule-of-thumb-for-usage With is not going to act inside functions, and permanently redefining Print is error-prone and inconvenient. – Szabolcs May 02 '12 at 13:31
  • @Szabolcs Thanks for pointing out some of the subtle properties of Block – image_doctor May 03 '12 at 12:56
  • How do I revert this? If I want to have Print work again as usual in the current Mathematica session? – a06e Feb 01 '16 at 15:47
  • @becko: As soon as the Block finishes execution, Print is automatically reverted to the previous value (which should be the original Print function, unless you did any further change to it outside the Block). If you want to re-enable Print while still inside the Block, just use Print =. to undo the assignment. – celtschk Jun 10 '16 at 17:16
2

This seemed to work for me.

ParallelEvaluate[Unprotect@Print];
ParallelEvaluate[Print = Null &];
ParallelDo[Print[{i, $KernelID}], {i, 1, 10}]

This also seemed to work:

ParallelDo[With[{Print = Null &}, Print[{i, $KernelID}]], {i, 1, 10}]
image_doctor
  • 10,234
  • 23
  • 40