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

36 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-20 14:51 +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 stats_now = filter_stats(result, time=t) 

31 for me in stats_now.keys(): 

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

33 

34 [ 

35 [ 

36 [result.pop(you, None) for you in filter_stats(stats_now, type=type_, num_restarts=i).keys()] 

37 for i in range(num_restarts_) 

38 ] 

39 for type_, num_restarts_ in restarts.items() 

40 ] 

41 

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

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

44 other_restarted_steps = [ 

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

46 ] 

47 for step in other_restarted_steps: 

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

49 

50 return result 

51 

52 

53def sort_stats(stats, sortby): 

54 """ 

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

56 

57 Args: 

58 stats (dict): dictionary of statistics 

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

60 

61 Returns: 

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

63 """ 

64 

65 result = [] 

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

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

68 item = getattr(k, sortby) 

69 result.append((item, v)) 

70 

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

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

73 

74 return sorted_data 

75 

76 

77def get_list_of_types(stats): 

78 """ 

79 Helper function to get list of types registered in stats 

80 

81 Args: 

82 stats (dict): dictionary with statistics 

83 

84 Returns: 

85 list: list of types registered 

86 

87 """ 

88 

89 type_list = [] 

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

91 if k.type not in type_list: 

92 type_list.append(k.type) 

93 return type_list 

94 

95 

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

97 """ 

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

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

100 

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

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

103 

104 Returns: 

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

106 """ 

107 

108 return sort_stats( 

109 filter_stats(stats, **kwargs), 

110 sortby=sortby, 

111 )