Add OpenMP simple breakdown support
For now we only show the breakdown of the label and subsystem, without the idle information.
This commit is contained in:
		
							parent
							
								
									1dcb3f4822
								
							
						
					
					
						commit
						81c137a65e
					
				| @ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||||||
| 
 | 
 | ||||||
| - Add support OpenMP label and task ID views. | - Add support OpenMP label and task ID views. | ||||||
| - Add support for nOS-V non-blocking scheduler server events (`VSN` and `VSn`). | - Add support for nOS-V non-blocking scheduler server events (`VSN` and `VSn`). | ||||||
|  | - Add OpenMP simple breakdown view. | ||||||
| 
 | 
 | ||||||
| ## [1.11.0] - 2024-11-08 | ## [1.11.0] - 2024-11-08 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										44
									
								
								cfg/cpu/openmp/breakdown.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								cfg/cpu/openmp/breakdown.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | #ParaverCFG | ||||||
|  | ConfigFile.Version: 3.4 | ||||||
|  | ConfigFile.NumWindows: 1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ################################################################################ | ||||||
|  | < NEW DISPLAYING WINDOW CPU: OpenMP Runtime/Label breakdown > | ||||||
|  | ################################################################################ | ||||||
|  | window_name CPU: OpenMP Runtime/Label breakdown | ||||||
|  | window_type single | ||||||
|  | window_id 1 | ||||||
|  | window_position_x 100 | ||||||
|  | window_position_y 100 | ||||||
|  | window_width 600 | ||||||
|  | window_height 150 | ||||||
|  | window_comm_lines_enabled false | ||||||
|  | window_flags_enabled false | ||||||
|  | window_noncolor_mode true | ||||||
|  | window_custom_color_enabled true | ||||||
|  | window_custom_color_palette {1.000000000000:255,177,245},{2.000000000000:255,86,239},{3.000000000000:122,44,22},{5.000000000000:239,188,0},{6.000000000000:160,89,0},{8.000000000000:0,255,73},{10.000000000000:86,209,43},{11.000000000000:203,208,93},{12.000000000000:0,176,169},{13.000000000000:190,82,201},{14.000000000000:124,114,183},{15.000000000000:157,231,255},{16.000000000000:199,194,0},{17.000000000000:96,0,200},{18.000000000000:255,255,124},{19.000000000000:35,152,0},{21.000000000000:255,251,174},{22.000000000000:232,0,0},{23.000000000000:210,66,40},{26.000000000000:101,101,99},{27.000000000000:200,0,255},{28.000000000000:0,203,249},{30.000000000000:255,219,0},{31.000000000000:48,103,107},{34.000000000000:194,105,126} {100.000000000000:0,100,0},{101.000000000000:162,155,60},{102.000000000000:124,0,0} | ||||||
|  | window_logical_filtered true | ||||||
|  | window_physical_filtered false | ||||||
|  | window_comm_fromto true | ||||||
|  | window_comm_tagsize true | ||||||
|  | window_comm_typeval true | ||||||
|  | window_units Microseconds | ||||||
|  | window_maximum_y 1000.0 | ||||||
|  | window_minimum_y 1.0 | ||||||
|  | window_compute_y_max true | ||||||
|  | window_level thread | ||||||
|  | window_scale_relative 1.000000000000 | ||||||
|  | window_end_time_relative 1.000000000000 | ||||||
|  | window_object appl { 1, { All } } | ||||||
|  | window_begin_time_relative 0.000000000000 | ||||||
|  | window_open true | ||||||
|  | window_drawmode draw_randnotzero | ||||||
|  | window_drawmode_rows draw_randnotzero | ||||||
|  | window_pixel_size 1 | ||||||
|  | window_labels_to_draw 1 | ||||||
|  | window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } } | ||||||
|  | window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } } | ||||||
|  | window_filter_module evt_type 1 53 | ||||||
|  | window_filter_module evt_type_label 1 "CPU: OpenMP Runtime/Label breakdown" | ||||||
|  | 
 | ||||||
| @ -177,6 +177,17 @@ currently running on each thread. The ID is a monotonically increasing | |||||||
| identifier assigned on task creation. Lower IDs correspond to tasks | identifier assigned on task creation. Lower IDs correspond to tasks | ||||||
| created at an earlier point than higher IDs. | created at an earlier point than higher IDs. | ||||||
| 
 | 
 | ||||||
|  | # Breakdown (simple) | ||||||
|  | 
 | ||||||
|  | A simplified view for the breakdown is generated when the emulator is run with | ||||||
|  | the `-b` flag, the trace is stored in `openmp-breakdown.prv`. This breakdown | ||||||
|  | view selects the label when it has a value or the subsystem otherwise. The view | ||||||
|  | is sorted so that rows with same values are grouped together. | ||||||
|  | 
 | ||||||
|  | Notice that unlike nOS-V or Nanos6, we don't include yet the information about | ||||||
|  | the runtime waiting or making progress, but some information can be inferred | ||||||
|  | from the subsystem states. | ||||||
|  | 
 | ||||||
| ## Limitations | ## Limitations | ||||||
| 
 | 
 | ||||||
| As the compiler generates the code that perform the calls to the libompv | As the compiler generates the code that perform the calls to the libompv | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| # Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC) | # Copyright (c) 2021-2025 Barcelona Supercomputing Center (BSC) | ||||||
| # SPDX-License-Identifier: GPL-3.0-or-later | # SPDX-License-Identifier: GPL-3.0-or-later | ||||||
| 
 | 
 | ||||||
| include_directories( | include_directories( | ||||||
| @ -65,6 +65,7 @@ add_library(emu STATIC | |||||||
|   kernel/event.c |   kernel/event.c | ||||||
|   openmp/setup.c |   openmp/setup.c | ||||||
|   openmp/event.c |   openmp/event.c | ||||||
|  |   openmp/breakdown.c | ||||||
| ) | ) | ||||||
| target_link_libraries(emu ovni-static) | target_link_libraries(emu ovni-static) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
 | /* Copyright (c) 2021-2025 Barcelona Supercomputing Center (BSC)
 | ||||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
| 
 | 
 | ||||||
| #ifndef EMU_PRV_H | #ifndef EMU_PRV_H | ||||||
| @ -35,6 +35,7 @@ enum emu_prv_types { | |||||||
| 	PRV_OPENMP_SUBSYSTEM = 50, | 	PRV_OPENMP_SUBSYSTEM = 50, | ||||||
| 	PRV_OPENMP_LABEL     = 51, | 	PRV_OPENMP_LABEL     = 51, | ||||||
| 	PRV_OPENMP_TASKID    = 52, | 	PRV_OPENMP_TASKID    = 52, | ||||||
|  | 	PRV_OPENMP_BREAKDOWN = 53, | ||||||
| 	PRV_OVNI_MARK        = 100, | 	PRV_OVNI_MARK        = 100, | ||||||
| 	/* User marks [100, 200) */ | 	/* User marks [100, 200) */ | ||||||
| 	PRV_RESERVED         = 200, | 	PRV_RESERVED         = 200, | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
 | /* Copyright (c) 2021-2025 Barcelona Supercomputing Center (BSC)
 | ||||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
| 
 | 
 | ||||||
| #include "nanos6_priv.h" | #include "nanos6_priv.h" | ||||||
| @ -313,7 +313,7 @@ model_nanos6_create(struct emu *emu) | |||||||
| 	extend_set(&emu->ext, model_id, e); | 	extend_set(&emu->ext, model_id, e); | ||||||
| 
 | 
 | ||||||
| 	if (model_nanos6_breakdown_create(emu) != 0) { | 	if (model_nanos6_breakdown_create(emu) != 0) { | ||||||
| 		err("model_nanos6_breakdown_connect failed"); | 		err("model_nanos6_breakdown_create failed"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										234
									
								
								src/emu/openmp/breakdown.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								src/emu/openmp/breakdown.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,234 @@ | |||||||
|  | /* Copyright (c) 2024-2025 Barcelona Supercomputing Center (BSC)
 | ||||||
|  |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
|  | 
 | ||||||
|  | #include "breakdown.h" | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "bay.h" | ||||||
|  | #include "chan.h" | ||||||
|  | #include "common.h" | ||||||
|  | #include "cpu.h" | ||||||
|  | #include "emu.h" | ||||||
|  | #include "emu_args.h" | ||||||
|  | #include "emu_prv.h" | ||||||
|  | #include "extend.h" | ||||||
|  | #include "model_cpu.h" | ||||||
|  | #include "mux.h" | ||||||
|  | #include "openmp_priv.h" | ||||||
|  | #include "proc.h" | ||||||
|  | #include "pv/pcf.h" | ||||||
|  | #include "pv/prf.h" | ||||||
|  | #include "pv/prv.h" | ||||||
|  | #include "pv/pvt.h" | ||||||
|  | #include "recorder.h" | ||||||
|  | #include "sort.h" | ||||||
|  | #include "system.h" | ||||||
|  | #include "task.h" | ||||||
|  | #include "track.h" | ||||||
|  | #include "value.h" | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  | 	MUX0_LABEL = 0, | ||||||
|  | 	MUX0_SUBSYSTEM = 1, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | create_cpu(struct bay *bay, struct breakdown_cpu *bcpu, int64_t gindex) | ||||||
|  | { | ||||||
|  | 	enum chan_type t = CHAN_SINGLE; | ||||||
|  | 	chan_init(&bcpu->out, t, "openmp.cpu%"PRIi64".breakdown.out", gindex); | ||||||
|  | 
 | ||||||
|  | 	if (bay_register(bay, &bcpu->out) != 0) { | ||||||
|  | 		err("bay_register out failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | model_openmp_breakdown_create(struct emu *emu) | ||||||
|  | { | ||||||
|  | 	if (emu->args.breakdown == 0) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	struct openmp_emu *memu = EXT(emu, 'P'); | ||||||
|  | 	struct breakdown_emu *bemu = &memu->breakdown; | ||||||
|  | 
 | ||||||
|  | 	/* Count phy cpus */ | ||||||
|  | 	struct system *sys = &emu->system; | ||||||
|  | 	int64_t nphycpus = (int64_t) (sys->ncpus - sys->nlooms); | ||||||
|  | 	bemu->nphycpus = nphycpus; | ||||||
|  | 
 | ||||||
|  | 	/* Create a new Paraver trace */ | ||||||
|  | 	struct recorder *rec = &emu->recorder; | ||||||
|  | 	bemu->pvt = recorder_add_pvt(rec, "openmp-breakdown", (long) nphycpus); | ||||||
|  | 	if (bemu->pvt == NULL) { | ||||||
|  | 		err("recorder_add_pvt failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (sort_init(&bemu->sort, &emu->bay, nphycpus, "openmp.breakdown.sort") != 0) { | ||||||
|  | 		err("sort_init failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) { | ||||||
|  | 		if (cpu->is_virtual) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		struct openmp_cpu *mcpu = EXT(cpu, 'P'); | ||||||
|  | 		struct breakdown_cpu *bcpu = &mcpu->breakdown; | ||||||
|  | 
 | ||||||
|  | 		if (create_cpu(&emu->bay, bcpu, cpu->gindex) != 0) { | ||||||
|  | 			err("create_cpu failed"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | select_mux0(struct mux *mux, struct value value, struct mux_input **input) | ||||||
|  | { | ||||||
|  | 	if (value.type != VALUE_NULL) | ||||||
|  | 		*input = mux_get_input(mux, MUX0_LABEL); /* label */ | ||||||
|  | 	else | ||||||
|  | 		*input = mux_get_input(mux, MUX0_SUBSYSTEM); /* subsystem */ | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | connect_cpu(struct bay *bay, struct openmp_cpu *mcpu) | ||||||
|  | { | ||||||
|  | 	struct breakdown_cpu *bcpu = &mcpu->breakdown; | ||||||
|  | 
 | ||||||
|  | 	/* Channel aliases */ | ||||||
|  | 	struct chan *subsystem = &mcpu->m.track[CH_SUBSYSTEM].ch; | ||||||
|  | 	struct chan *label = &mcpu->m.track[CH_LABEL].ch; | ||||||
|  | 	struct chan *out = &bcpu->out; | ||||||
|  | 
 | ||||||
|  | 	if (mux_init(&bcpu->mux0, bay, label, out, select_mux0, 2) != 0) { | ||||||
|  | 		err("mux_init failed for mux0"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (mux_set_input(&bcpu->mux0, MUX0_LABEL, label) != 0) { | ||||||
|  | 		err("mux_set_input subsystem failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (mux_set_input(&bcpu->mux0, MUX0_SUBSYSTEM, subsystem) != 0) { | ||||||
|  | 		err("mux_set_input label failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | model_openmp_breakdown_connect(struct emu *emu) | ||||||
|  | { | ||||||
|  | 	if (emu->args.breakdown == 0) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	struct openmp_emu *memu = EXT(emu, 'P'); | ||||||
|  | 	struct breakdown_emu *bemu = &memu->breakdown; | ||||||
|  | 	struct bay *bay = &emu->bay; | ||||||
|  | 	struct system *sys = &emu->system; | ||||||
|  | 
 | ||||||
|  | 	int64_t i = 0; | ||||||
|  | 	for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) { | ||||||
|  | 		if (cpu->is_virtual) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		struct openmp_cpu *mcpu = EXT(cpu, 'P'); | ||||||
|  | 		struct breakdown_cpu *bcpu = &mcpu->breakdown; | ||||||
|  | 
 | ||||||
|  | 		/* Connect tri channels and muxes */ | ||||||
|  | 		if (connect_cpu(bay, mcpu) != 0) { | ||||||
|  | 			err("connect_cpu failed"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* Connect out to sort */ | ||||||
|  | 		if (sort_set_input(&bemu->sort, i, &bcpu->out) != 0) { | ||||||
|  | 			err("sort_set_input failed"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* Connect out to PRV */ | ||||||
|  | 		struct prv *prv = pvt_get_prv(bemu->pvt); | ||||||
|  | 		long type = PRV_OPENMP_BREAKDOWN; | ||||||
|  | 		long flags = PRV_SKIPDUP; | ||||||
|  | 
 | ||||||
|  | 		/* We may emit zero at the start, when an input changes and all
 | ||||||
|  | 		 * the other sort output channels write a zero in the output, | ||||||
|  | 		 * before the last value is set in prv.c. */ | ||||||
|  | 		flags |= PRV_ZERO; | ||||||
|  | 
 | ||||||
|  | 		struct chan *out = sort_get_output(&bemu->sort, i); | ||||||
|  | 		if (prv_register(prv, (long) i, type, bay, out, flags)) { | ||||||
|  | 			err("prv_register failed"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		i++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | model_openmp_breakdown_finish(struct emu *emu, | ||||||
|  | 		const struct pcf_value_label **labels) | ||||||
|  | { | ||||||
|  | 	if (emu->args.breakdown == 0) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	struct openmp_emu *memu = EXT(emu, 'P'); | ||||||
|  | 	struct breakdown_emu *bemu = &memu->breakdown; | ||||||
|  | 	struct pcf *pcf = pvt_get_pcf(bemu->pvt); | ||||||
|  | 	long typeid = PRV_OPENMP_BREAKDOWN; | ||||||
|  | 	char label[] = "CPU: OpenMP Runtime/Label breakdown"; | ||||||
|  | 	struct pcf_type *pcftype = pcf_add_type(pcf, (int) typeid, label); | ||||||
|  | 	const struct pcf_value_label *v = NULL; | ||||||
|  | 
 | ||||||
|  | 	/* Emit subsystem values */ | ||||||
|  | 	for (v = labels[CH_SUBSYSTEM]; v->label; v++) { | ||||||
|  | 		if (pcf_add_value(pcftype, v->value, v->label) == NULL) { | ||||||
|  | 			err("pcf_add_value ss failed"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Emit label values */ | ||||||
|  | 	struct system *sys = &emu->system; | ||||||
|  | 	for (struct proc *p = sys->procs; p; p = p->gnext) { | ||||||
|  | 		struct openmp_proc *proc = EXT(p, 'P'); | ||||||
|  | 		struct task_info *info = &proc->task_info; | ||||||
|  | 		if (task_create_pcf_types(pcftype, info->types) != 0) { | ||||||
|  | 			err("task_create_pcf_types failed"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Also populate the row labels */ | ||||||
|  | 	struct prf *prf = pvt_get_prf(bemu->pvt); | ||||||
|  | 	for (int64_t row = 0; row < bemu->nphycpus; row++) { | ||||||
|  | 		char name[128]; | ||||||
|  | 		if (snprintf(name, 128, "~CPU %4" PRIi64, bemu->nphycpus - row) >= 128) { | ||||||
|  | 			err("label too long"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (prf_add(prf, (long) row, name) != 0) { | ||||||
|  | 			err("prf_add failed for %s", name); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								src/emu/openmp/breakdown.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/emu/openmp/breakdown.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | /* Copyright (c) 2024-2025 Barcelona Supercomputing Center (BSC)
 | ||||||
|  |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
|  | 
 | ||||||
|  | #ifndef BREAKDOWN_H | ||||||
|  | #define BREAKDOWN_H | ||||||
|  | 
 | ||||||
|  | /* 
 | ||||||
|  |  * The breakdown model is implemented on top of the CPU label and subsystem | ||||||
|  |  * channels. The mux selects the label when the . | ||||||
|  |  * | ||||||
|  |  *                +--------+ | ||||||
|  |  *                |        | | ||||||
|  |  *                |        v | ||||||
|  |  *                |     +------+ | ||||||
|  |  *    label ------o-->--|      | | ||||||
|  |  *                      | mux0 |-->- out | ||||||
|  |  *    subsystem ----->--|      | | ||||||
|  |  *                      +------+ | ||||||
|  |  * | ||||||
|  |  *    mux0 output = label if sel is not null, subsystem otherwise. | ||||||
|  |  * | ||||||
|  |  * Then the sort module takes the output of each CPU and sorts the values which | ||||||
|  |  * are propagated to the PRV directly. | ||||||
|  |  * | ||||||
|  |  *                    +------+       +-----+ | ||||||
|  |  *    cpu0.out --->---|      |--->---|     | | ||||||
|  |  *    ...             | sort |  ...  | PRV | | ||||||
|  |  *    cpuN.out --->---|      |--->---|     | | ||||||
|  |  *                    +------+       +-----+ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "chan.h" | ||||||
|  | #include "mux.h" | ||||||
|  | #include "sort.h" | ||||||
|  | 
 | ||||||
|  | struct breakdown_cpu { | ||||||
|  | 	struct mux  mux0; | ||||||
|  | 	struct chan out; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct breakdown_emu { | ||||||
|  | 	int64_t nphycpus; | ||||||
|  | 	struct sort sort; | ||||||
|  | 	struct pvt *pvt; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif /* BREAKDOWN_H */ | ||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
 | /* Copyright (c) 2023-2025 Barcelona Supercomputing Center (BSC)
 | ||||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
| 
 | 
 | ||||||
| #ifndef OPENMP_PRIV_H | #ifndef OPENMP_PRIV_H | ||||||
| @ -8,6 +8,7 @@ | |||||||
| #include "task.h" | #include "task.h" | ||||||
| #include "model_cpu.h" | #include "model_cpu.h" | ||||||
| #include "model_thread.h" | #include "model_thread.h" | ||||||
|  | #include "breakdown.h" | ||||||
| 
 | 
 | ||||||
| /* Private enums */ | /* Private enums */ | ||||||
| 
 | 
 | ||||||
| @ -63,6 +64,7 @@ struct openmp_thread { | |||||||
| 
 | 
 | ||||||
| struct openmp_cpu { | struct openmp_cpu { | ||||||
| 	struct model_cpu m; | 	struct model_cpu m; | ||||||
|  | 	struct breakdown_cpu breakdown; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct openmp_proc { | struct openmp_proc { | ||||||
| @ -70,10 +72,19 @@ struct openmp_proc { | |||||||
| 	struct task_info task_info; | 	struct task_info task_info; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct openmp_emu { | ||||||
|  | 	struct breakdown_emu breakdown; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| int model_openmp_probe(struct emu *emu); | int model_openmp_probe(struct emu *emu); | ||||||
| int model_openmp_create(struct emu *emu); | int model_openmp_create(struct emu *emu); | ||||||
| int model_openmp_connect(struct emu *emu); | int model_openmp_connect(struct emu *emu); | ||||||
| int model_openmp_event(struct emu *emu); | int model_openmp_event(struct emu *emu); | ||||||
| int model_openmp_finish(struct emu *emu); | int model_openmp_finish(struct emu *emu); | ||||||
| 
 | 
 | ||||||
|  | int model_openmp_breakdown_create(struct emu *emu); | ||||||
|  | int model_openmp_breakdown_connect(struct emu *emu); | ||||||
|  | int model_openmp_breakdown_finish(struct emu *emu, | ||||||
|  | 		const struct pcf_value_label **labels); | ||||||
|  | 
 | ||||||
| #endif /* OPENMP_PRIV_H */ | #endif /* OPENMP_PRIV_H */ | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
 | /* Copyright (c) 2023-2025 Barcelona Supercomputing Center (BSC)
 | ||||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ |  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||||
| 
 | 
 | ||||||
| #include "openmp_priv.h" | #include "openmp_priv.h" | ||||||
| @ -278,6 +278,19 @@ model_openmp_create(struct emu *emu) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	struct openmp_emu *e = calloc(1, sizeof(struct openmp_emu)); | ||||||
|  | 	if (e == NULL) { | ||||||
|  | 		err("calloc failed:"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	extend_set(&emu->ext, model_id, e); | ||||||
|  | 
 | ||||||
|  | 	if (model_openmp_breakdown_create(emu) != 0) { | ||||||
|  | 		err("model_openmp_breakdown_create failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -294,6 +307,11 @@ model_openmp_connect(struct emu *emu) | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (model_openmp_breakdown_connect(emu) != 0) { | ||||||
|  | 		err("model_openmp_breakdown_connect failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -379,6 +397,11 @@ model_openmp_finish(struct emu *emu) | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (model_openmp_breakdown_finish(emu, pcf_labels) != 0) { | ||||||
|  | 		err("model_openmp_breakdown_finish failed"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* When running in linter mode perform additional checks */ | 	/* When running in linter mode perform additional checks */ | ||||||
| 	if (emu->args.linter_mode && end_lint(emu) != 0) { | 	if (emu->args.linter_mode && end_lint(emu) != 0) { | ||||||
| 		err("end_lint failed"); | 		err("end_lint failed"); | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ if(NOT NOSV_FOUND) | |||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| function(openmp_rt_test) | function(openmp_rt_test) | ||||||
|   ovni_test(${ARGN}) |   ovni_test(${ARGN} SORT) | ||||||
|   target_compile_options("${OVNI_TEST_NAME}" PUBLIC "-fopenmp=libompv" |   target_compile_options("${OVNI_TEST_NAME}" PUBLIC "-fopenmp=libompv" | ||||||
| 	  "-no-pedantic") | 	  "-no-pedantic") | ||||||
|   target_link_options("${OVNI_TEST_NAME}" PUBLIC "-fopenmp=libompv") |   target_link_options("${OVNI_TEST_NAME}" PUBLIC "-fopenmp=libompv") | ||||||
| @ -34,7 +34,7 @@ function(openmp_rt_test) | |||||||
|   set_property(TEST "${OVNI_TEST_NAME}" APPEND PROPERTY |   set_property(TEST "${OVNI_TEST_NAME}" APPEND PROPERTY | ||||||
|     ENVIRONMENT "OMP_OVNI=1") |     ENVIRONMENT "OMP_OVNI=1") | ||||||
|   set_property(TEST "${OVNI_TEST_NAME}" APPEND PROPERTY |   set_property(TEST "${OVNI_TEST_NAME}" APPEND PROPERTY | ||||||
|     ENVIRONMENT "NOSV_CONFIG_OVERRIDE=instrumentation.version=ovni") |     ENVIRONMENT "NOSV_CONFIG_OVERRIDE=instrumentation.version=ovni,ovni.level=3") | ||||||
| endfunction() | endfunction() | ||||||
| 
 | 
 | ||||||
| openmp_rt_test(active.c DRIVER active.driver.sh) | openmp_rt_test(active.c DRIVER active.driver.sh) | ||||||
| @ -55,7 +55,7 @@ openmp_rt_test(taskloop.c) | |||||||
| openmp_rt_test(taskwait.c) | openmp_rt_test(taskwait.c) | ||||||
| openmp_rt_test(team-distribute.c) | openmp_rt_test(team-distribute.c) | ||||||
| openmp_rt_test(worksharing-and-tasks.c) | openmp_rt_test(worksharing-and-tasks.c) | ||||||
| openmp_rt_test(worksharing-mix.c) | openmp_rt_test(worksharing-mix.c BREAKDOWN) | ||||||
| openmp_rt_test(worksharing-task.c) | openmp_rt_test(worksharing-task.c) | ||||||
| openmp_rt_test(worksharing.c) | openmp_rt_test(worksharing.c) | ||||||
| openmp_rt_test(worksharing01.c) | openmp_rt_test(worksharing01.c) | ||||||
|  | |||||||
| @ -5,6 +5,8 @@ export OMP_NUM_THREADS=1 | |||||||
| 
 | 
 | ||||||
| $target | $target | ||||||
| 
 | 
 | ||||||
|  | ovnisort ovni | ||||||
|  | 
 | ||||||
| ovniemu -l ovni | ovniemu -l ovni | ||||||
| 
 | 
 | ||||||
| # Mark API adds 100 to the type | # Mark API adds 100 to the type | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ int main(void) | |||||||
| 		#pragma omp single | 		#pragma omp single | ||||||
| 		for (int i = 0; i < 100; i++) | 		for (int i = 0; i < 100; i++) | ||||||
| 		{ | 		{ | ||||||
| 			#pragma omp task | 			#pragma omp task label("mini-task") | ||||||
| 			sleep_us(10); | 			sleep_us(10); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user