text: Title: Optimize iterative tiling via pruning intermediate chunks
  Body: <!--
  Thank you for your contribution!
  
  Please review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.
  -->
  
  ## Background
  
  Iterative tiling is used during `tile` of an operand when the input tileable has unknown shape, or the operand want to trigger part of input chunks to perform an algorithm based on the input data. For instance, `df.groupby().agg()` will decide to use `tree` or `shuffle` according to the aggregated size of the first 4 chunks.
  
  However, iterative tiling may trigger the execution of all inputs tileables and the memory usage may increase significantly. Still take the `df.groupby().agg()` as an example.
  
  ```python
  import mars.dataframe as md
  import mars.tensor as mt
  df = md.DataFrame(mt.random.rand(1000, 10, chunk_size=100))
  df.groupby(0).agg('sum').execute(extra_config={'dump_subtask_graph': True})
  ```
  
  The graph shows:
  
  ![image](https://user-images.githubusercontent.com/357506/160064742-3d3286b8-9f4d-4c93-a52e-dbebc82c6274.png)
  
  Other than the 4 aggregated chunks that yielded inside `tile`, all the other 6 `DataFrameFromTensor` chunks are submitted as well, this may cause huge memory occupation.
  
  ## Solution
  
  We suggest solutions as below:
  
  1. If a `tile` triggered iterative tiling, the yielded chunks should be included in result chunks, if no chunks yielded, the input chunks are treated as result chunks.
  2. If a tileable is in result tileables, its chunks are included in result chunks.
  3. Otherwise, chunks that are not used by result chunks will be pruned.