Coverage for pySDC/helpers/stats_helper.py: 100%

35 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-29 09:02 +0000

1import numpy as np 

2 

3 

4def filter_stats(stats, comm=None, recomputed=None, **kwargs): 

5 """ 

6 Helper function to extract data from the dictionary of statistics. Please supply metadata as keyword arguments. 

7 

8 Args: 

9 stats (dict): raw statistics from a controller run 

10 recomputed (bool): filter recomputed values from stats if set to anything other than None 

11 comm (mpi4py.MPI.Intracomm): Communicator (or None if not applicable) 

12 

13 Returns: 

14 dict: dictionary containing only the entries corresponding to the filter 

15 """ 

16 result = {} 

17 for k, v in stats.items(): 

18 if all([k._asdict().get(k2, None) == v2 for k2, v2 in kwargs.items() if v2 is not None] + [True]): 

19 result[k] = v 

20 

21 if comm is not None: 

22 # gather the results across all ranks 

23 result = {key: value for sub_result in comm.allgather(result) for key, value in sub_result.items()} 

24 

25 if recomputed is not None: 

26 # delete values that have been recorded and superseded by similar, but not identical keys 

27 times_restarted = np.unique([me.time for me in result.keys() if me.num_restarts > 0]) 

28 for t in times_restarted: 

29 restarts = {} 

30 for me in filter_stats(result, time=t).keys(): 

31 restarts[me.type] = max([restarts.get(me.type, 0), me.num_restarts]) 

32 

33 [ 

34 [ 

35 [result.pop(you, None) for you in filter_stats(result, time=t, type=type_, num_restarts=i).keys()] 

36 for i in range(num_restarts_) 

37 ] 

38 for type_, num_restarts_ in restarts.items() 

39 ] 

40 

41 # delete values that were recorded at times that shouldn't be recorded because we performed a different step after the restart 

42 if kwargs.get('type', None) != '_recomputed': 

43 other_restarted_steps = [ 

44 key for key, val in filter_stats(stats, type='_recomputed', recomputed=False, comm=comm).items() if val 

45 ] 

46 for step in other_restarted_steps: 

47 [result.pop(me) for me in filter_stats(result, time=step.time).keys()] 

48 

49 return result 

50 

51 

52def sort_stats(stats, sortby): 

53 """ 

54 Helper function to transform stats dictionary to sorted list of tuples 

55 

56 Args: 

57 stats (dict): dictionary of statistics 

58 sortby (str): string to specify which key to use for sorting 

59 

60 Returns: 

61 list: list of tuples containing the sortby item and the value 

62 """ 

63 

64 result = [] 

65 for k, v in stats.items(): 

66 # convert string to attribute and append key + value to result as tuple 

67 item = getattr(k, sortby) 

68 result.append((item, v)) 

69 

70 # sort by first element of the tuple (which is the sortby key) and return 

71 sorted_data = sorted(result, key=lambda tup: tup[0]) 

72 

73 return sorted_data 

74 

75 

76def get_list_of_types(stats): 

77 """ 

78 Helper function to get list of types registered in stats 

79 

80 Args: 

81 stats (dict): dictionary with statistics 

82 

83 Returns: 

84 list: list of types registered 

85 

86 """ 

87 

88 type_list = [] 

89 for k, _ in stats.items(): 

90 if k.type not in type_list: 

91 type_list.append(k.type) 

92 return type_list 

93 

94 

95def get_sorted(stats, sortby='time', **kwargs): 

96 """ 

97 Utility for filtering and sorting stats in a single call. Pass a communicator if using MPI. 

98 Keyword arguments are passed to `filter_stats` for filtering. 

99 

100 stats (dict): raw statistics from a controller run 

101 sortby (str): string to specify which key to use for sorting 

102 

103 Returns: 

104 list: list of tuples containing the sortby item and the value 

105 """ 

106 

107 return sort_stats( 

108 filter_stats(stats, **kwargs), 

109 sortby=sortby, 

110 )