def emissions_comparison(process_kwh, locations, year): # TODO: Disambiguation of states such as Georgia, US and Georgia intl_data = utils.get_data("data/json/energy-mix-intl_" + year + ".json") us_data = utils.get_data("data/json/us-emissions_" + year + ".json") emissions = [] # list of tuples w/ format (location, emission) for location in locations: if locate.in_US(location): emission = convert.lbs_to_kgs(us_data[location] * convert.to_MWh(process_kwh)) emissions.append((location, emission)) else: c = intl_data[location] total, breakdown = c['total'], [c['coal'], c['petroleum'], \ c['naturalGas'], c['lowCarbon']] if isinstance(total, float) and float(total) > 0: breakdown = list(map(lambda x: 100 * x / total, breakdown)) coal, petroleum, natural_gas, low_carbon = breakdown breakdown = [ convert.coal_to_carbon(process_kwh * coal / 100), convert.petroleum_to_carbon(process_kwh * petroleum / 100), convert.natural_gas_to_carbon(process_kwh * natural_gas / 100), 0 ] emission = sum(breakdown) emissions.append((location, emission)) if emissions != []: utils.log('Emissions Comparison', emissions) return emissions
def old_emissions_comparison(process_kwh, year, default_location, printToScreen): # Calculates emissions in different locations intl_data = utils.get_data("data/json/energy-mix-intl_" + year + ".json") global_emissions, europe_emissions, us_emissions = [], [], [] # Handling international for country in intl_data: c = intl_data[country] total, breakdown = c['total'], [c['coal'], c['petroleum'], \ c['naturalGas'], c['lowCarbon']] if isinstance(total, float) and float(total) > 0: breakdown = list(map(lambda x: 100 * x / total, breakdown)) coal, petroleum, natural_gas, low_carbon = breakdown breakdown = [ convert.coal_to_carbon(process_kwh * coal / 100), convert.petroleum_to_carbon(process_kwh * petroleum / 100), convert.natural_gas_to_carbon(process_kwh * natural_gas / 100), 0 ] emission = sum(breakdown) if locate.in_Europe(country): europe_emissions.append((country, emission)) else: global_emissions.append((country, emission)) global_emissions.sort(key=lambda x: x[1]) europe_emissions.sort(key=lambda x: x[1]) # Handling US us_data = utils.get_data("data/json/us-emissions_" + year + ".json") for state in us_data: if ((state != "United States") and state != "_units"): if us_data[state] != "lbs/MWh": emission = convert.lbs_to_kgs(us_data[state] * convert.to_MWh(process_kwh)) us_emissions.append((state, emission)) us_emissions.sort(key=lambda x: x[1]) max_global, max_europe, max_us = global_emissions[len(global_emissions)-1], \ europe_emissions[len(europe_emissions)-1], us_emissions[len(us_emissions)-1] median_global, median_europe, median_us = global_emissions[len(global_emissions)//2], \ europe_emissions[len(europe_emissions)//2], us_emissions[len(us_emissions)//2] min_global, min_europe, min_us = global_emissions[0], europe_emissions[ 0], us_emissions[0] if default_location and printToScreen: utils.log('Emissions Comparison default', max_global, median_global, min_global, max_europe, \ median_europe, min_europe, max_us, median_us, min_us) default_emissions = [max_global, median_global, min_global, max_europe, \ median_europe, min_europe, max_us, median_us, min_us] return default_emissions
def emissions(process_kwh, breakdown, location, year): """ Calculates the CO2 emitted by the program based on the location Parameters: process_kwh (int): kWhs used by the process breakdown (list): energy mix corresponding to user's location location (str): location of user Returns: emission (float): kilograms of CO2 emitted state_emission (float): lbs CO2 per MWh; 0 if international location """ if process_kwh < 0: raise OSError( "Process wattage lower than baseline wattage. Do not run other processes" " during the evaluation, or try evaluating a more resource-intensive process." ) utils.log("Energy Data", breakdown, location) state_emission = 0 # Case 1: Unknown location, default to US data # Case 2: United States location if locate.in_US(location): if location == "Unknown": location = "United States" # US Emissions data is in lbs/Mwh data = utils.get_data("data/json/us-emissions_" + year + ".json") state_emission = data[location] emission = convert.lbs_to_kgs(state_emission * convert.to_MWh(process_kwh)) # Case 3: International location else: # Breaking down energy mix coal, petroleum, natural_gas, low_carbon = breakdown breakdown = [ convert.coal_to_carbon(process_kwh * coal / 100), convert.petroleum_to_carbon(process_kwh * petroleum / 100), convert.natural_gas_to_carbon(process_kwh * natural_gas / 100), 0 ] emission = sum(breakdown) utils.log("Emissions", emission) return (emission, state_emission)
def evaluate(user_func, *args, pdf=False, powerLoss=0.8, energyOutput=False, \ location_of_default = "GlobalAverage", printToScreen = True): """ Calculates effective emissions of the function Parameters: user_func: user inputtted function pdf (bool): whether a PDF report should be generated powerLoss (float): PSU efficiency rating """ utils.setGlobal(printToScreen) if (utils.valid_cpu() or utils.valid_gpu()): location = locate.get(printToScreen) result, return_value, watt_averages, files, total_time = energy(user_func, *args, powerLoss=powerLoss, \ printToScreen = printToScreen) breakdown = energy_mix(location, location_of_default) emission, state_emission = emissions(result, breakdown, location, location_of_default) utils.log("Assumed Carbon Equivalencies") emissions_comparison(result) utils.log("Process Energy", result) if pdf: report.generate(location, watt_averages, breakdown, emission, state_emission) if energyOutput: return (total_time, result, return_value) else: return return_value else: utils.log( "The energy-usage package only works on Linux kernels " "with Intel processors that support the RAPL interface and/or machines with" " an Nvidia GPU. Please try again on a different machine.")
def evaluate(user_func, *args, pdf=False, powerLoss=0.8, energyOutput=False, \ locations=["Mongolia", "Iceland", "Switzerland"], year="2016", printToScreen = True): """ Calculates effective emissions of the function Parameters: user_func: user's function + associated args pdf (bool): whether a PDF report should be generated powerLoss (float): PSU efficiency rating energyOutput (bool): return value also includes information about energy usage, not just function's return locations (list of strings): list of locations to be compared year (str): year of dataset to be used printToScreen (bool): get information in the command line """ utils.setGlobal(printToScreen) if (utils.valid_cpu() or utils.valid_gpu()): location = locate.get(printToScreen) result, return_value, watt_averages, files, total_time = energy(user_func, *args, powerLoss = powerLoss, year = year, \ printToScreen = printToScreen) default_location = False if locations == ["Mongolia", "Iceland", "Switzerland"]: default_location = True breakdown = energy_mix(location, year=year) emission, state_emission = emissions(result, breakdown, location, year, printToScreen) if printToScreen: utils.log("Assumed Carbon Equivalencies") comparison_values = emissions_comparison(result, locations, year, default_location, printToScreen) default_emissions = old_emissions_comparison(result, year, default_location, printToScreen) if printToScreen: utils.log("Process Energy", result) func_info = [user_func.__name__, *args] kwh_and_emissions = [result, emission, state_emission] if pdf: #pass report.generate(location, watt_averages, breakdown, kwh_and_emissions, \ func_info, comparison_values, default_emissions, default_location) if energyOutput: return (total_time, result, return_value) else: return return_value else: utils.log( "The energy-usage package only works on Linux kernels " "with Intel processors that support the RAPL interface and/or machines with" " an Nvidia GPU. Please try again on a different machine.")
def energy(user_func, *args, powerLoss=0.8, year, printToScreen): """ Evaluates the kwh needed for your code to run Parameters: user_func (function): user's function Returns: (process_kwh, return_value, watt_averages) """ baseline_check_seconds = 2 files, multiple_cpus = utils.get_files() is_nvidia_gpu = utils.valid_gpu() is_valid_cpu = utils.valid_cpu() # GPU handling if Nvidia gpu_baseline = [0] gpu_process = [0] bash_command = "nvidia-smi -i 0 --format=csv,noheader --query-gpu=power.draw" for i in range(int(baseline_check_seconds / DELAY)): if is_nvidia_gpu: output = subprocess.check_output(['bash', '-c', bash_command]) output = float(output.decode("utf-8")[:-2]) gpu_baseline.append(output) if is_valid_cpu: files = utils.measure_files(files, DELAY) files = utils.update_files(files) else: time.sleep(DELAY) # Adds the most recent value of GPU; 0 if not Nvidia last_reading = utils.get_total(files, multiple_cpus) + gpu_baseline[-1] if last_reading >= 0: utils.log("Baseline wattage", last_reading) if printToScreen: utils.newline() # Running the process and measuring wattage q = Queue() p = Process(target=func, args=( user_func, q, *args, )) start = timer() p.start() small_delay_counter = 0 return_value = None while (p.is_alive()): # Checking at a faster rate for quick processes if (small_delay_counter > DELAY): delay = DELAY / 10 small_delay_counter += 1 else: delay = DELAY if is_nvidia_gpu: output = subprocess.check_output(['bash', '-c', bash_command]) output = float(output.decode("utf-8")[:-2]) gpu_process.append(output) if is_valid_cpu: files = utils.measure_files(files, delay) files = utils.update_files(files, True) else: time.sleep(delay) # Just output, not added last_reading = (utils.get_total(files, multiple_cpus) + gpu_process[-1]) / powerLoss if last_reading >= 0: utils.log("Process wattage", last_reading) # Getting the return value of the user's function try: return_value = q.get_nowait() break except queue.Empty: pass p.join() end = timer() for file in files: file.process = file.process[1:-1] file.baseline = file.baseline[1:-1] if is_nvidia_gpu: gpu_baseline_average = statistics.mean(gpu_baseline[2:-1]) gpu_process_average = statistics.mean(gpu_process[2:-1]) else: gpu_baseline_average = 0 gpu_process_average = 0 total_time = end - start # seconds # Formatting the time nicely timedelta = str(datetime.timedelta(seconds=total_time)).split('.')[0] files = utils.average_files(files) process_average = utils.get_process_average(files, multiple_cpus, gpu_process_average) baseline_average = utils.get_baseline_average(files, multiple_cpus, gpu_baseline_average) difference_average = process_average - baseline_average watt_averages = [ baseline_average, process_average, difference_average, timedelta ] # Subtracting baseline wattage to get more accurate result process_kwh = convert.to_kwh( (process_average - baseline_average) * total_time) / powerLoss if is_nvidia_gpu: gpu_file = file("GPU", "") gpu_file.create_gpu(gpu_baseline_average, gpu_process_average) files.append(file("GPU", "")) # Logging utils.log("Final Readings", baseline_average, process_average, difference_average, timedelta) return (process_kwh, return_value, watt_averages, files, total_time)