mirror of
				https://github.com/ClusterCockpit/cc-backend
				synced 2025-10-31 16:05:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			254 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl
 | |
| 
 | |
| use strict;
 | |
| use warnings;
 | |
| use utf8;
 | |
| 
 | |
| my %INFO;
 | |
| my %DOMAINS;
 | |
| 
 | |
| my $SMT;
 | |
| my $numMemoryDomains;
 | |
| $DOMAINS{socket} = [];
 | |
| $DOMAINS{memoryDomain} = [];
 | |
| $DOMAINS{core} = [];
 | |
| $DOMAINS{gpu} = [];
 | |
| 
 | |
| my $gpuID=-1;
 | |
| my $id;
 | |
| 
 | |
| # Step 1 : Extract system information
 | |
| my $topo = `likwid-topology -O -G`;
 | |
| $INFO{numGPUs} = 0;
 | |
| 
 | |
| foreach my $ln (split("\n", $topo)) {
 | |
|     if ( $ln =~ /^STRUCT,NUMA Topology ([0-9]+)/ ) {
 | |
|         $id = $1;
 | |
|     }
 | |
|     if ( $ln =~ /^Processors/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         shift @fields;
 | |
|         $DOMAINS{memoryDomain}[$id] = [ @fields ];
 | |
|     }
 | |
|     if ( $ln =~ /^STRUCT,Cache Topology L1/ ) {
 | |
|         $id = -1;
 | |
|     }
 | |
|     if ( $ln =~ /^Cache groups/ ) {
 | |
|         if ( $id == -1 ) {
 | |
|             my @fields = split(",", $ln);
 | |
|             shift @fields;
 | |
|             my $i = 0;
 | |
|             foreach my $core ( @fields ) {
 | |
|                 $DOMAINS{core}[$i++] = [ split(" ", $core) ];
 | |
|             }
 | |
|             $id = 0;
 | |
|         }
 | |
|     }
 | |
|     if ( $ln =~ /^ID:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $gpuID = $fields[1];
 | |
|     }
 | |
|     if ( $gpuID >= 0 ) {
 | |
|         if ( $ln =~ /^Name:/ ) {
 | |
|             my @fields = split(",", $ln);
 | |
|             $DOMAINS{gpu}[$gpuID] = {};
 | |
|             $DOMAINS{gpu}[$gpuID]{model} = $fields[1];
 | |
|             if ( $fields[1] =~ /nvidia/i ) {
 | |
|                 $DOMAINS{gpu}[$gpuID]{type} = "Nvidia GPU";
 | |
|             } elsif  ( $fields[1] =~ /amd/i ) {
 | |
|                 $DOMAINS{gpu}[$gpuID]{type} = "AMD GPU";
 | |
|             } elsif  ( $fields[1] =~ /intel/i ) {
 | |
|                 $DOMAINS{gpu}[$gpuID]{type} = "Intel GPU";
 | |
|             }
 | |
|         }
 | |
|         if ( $ln =~ /^PCI bus:/ ) {
 | |
|             my @fields = split(",", $ln);
 | |
|             $fields[1] =~ s/0x//;
 | |
|             $DOMAINS{gpu}[$gpuID]{bus} = $fields[1];
 | |
|         }
 | |
|         if ( $ln =~ /^PCI domain:/ ) {
 | |
|             my @fields = split(",", $ln);
 | |
|             $fields[1] =~ s/0x//;
 | |
|             $DOMAINS{gpu}[$gpuID]{domain} = $fields[1];
 | |
|         }
 | |
|         if ( $ln =~ /^PCI device/ ) {
 | |
|             my @fields = split(",", $ln);
 | |
|             $fields[1] =~ s/0x//;
 | |
|             $DOMAINS{gpu}[$gpuID]{device} = $fields[1];
 | |
|             $gpuID = -1;
 | |
|         }
 | |
|     }
 | |
|     if ( $ln =~ /^CPU name:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $INFO{processor} = $fields[1];
 | |
|     }
 | |
|     if ( $ln =~ /^CPU type/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $INFO{family} = $fields[1];
 | |
|         $INFO{family} =~ s/[\(\)]//g;
 | |
|     }
 | |
|     if ( $ln =~ /^Sockets:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $INFO{socketsPerNode} = $fields[1];
 | |
|     }
 | |
|     if ( $ln =~ /^Cores per socket:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $INFO{coresPerSocket} = $fields[1];
 | |
|     }
 | |
|     if ( $ln =~ /^GPU count:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $INFO{numGPUs} = $fields[1];
 | |
|     }
 | |
|     if ( $ln =~ /^Threads per core:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $SMT = $fields[1];
 | |
|         $INFO{threadsPerCore} = $SMT;
 | |
|     }
 | |
|     if ( $ln =~ /^NUMA domains:/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         $INFO{memoryDomainsPerNode} = $fields[1];
 | |
|     }
 | |
|     if ( $ln =~ /^Socket ([0-9]+)/ ) {
 | |
|         my @fields = split(",", $ln);
 | |
|         shift @fields;
 | |
|         $DOMAINS{socket}[$1] = [ @fields ];
 | |
|     }
 | |
| }
 | |
| 
 | |
| my $node;
 | |
| my @sockets;
 | |
| my @nodeCores;
 | |
| foreach my $socket ( @{$DOMAINS{socket}} ) {
 | |
|     push @sockets, "[".join(",", @{$socket})."]";
 | |
|     push @nodeCores, join(",", @{$socket});
 | |
| }
 | |
| $node =  join(",", @nodeCores);
 | |
| $INFO{sockets} = join(",\n", @sockets);
 | |
| 
 | |
| my @memDomains;
 | |
| foreach my $d ( @{$DOMAINS{memoryDomain}} ) {
 | |
|     push @memDomains, "[".join(",", @{$d})."]";
 | |
| }
 | |
| $INFO{memoryDomains} = join(",\n", @memDomains);
 | |
| 
 | |
| my @cores;
 | |
| foreach my $c ( @{$DOMAINS{core}} ) {
 | |
|     push @cores, "[".join(",", @{$c})."]";
 | |
| }
 | |
| $INFO{cores} = join(",", @cores);
 | |
| 
 | |
| my $numCoresPerNode = $INFO{coresPerSocket} * $INFO{socketsPerNode};
 | |
| my $numCoresPerMemoryDomain = $numCoresPerNode / $INFO{memoryDomainsPerNode};
 | |
| my $memBw;
 | |
| 
 | |
| my $exp = join(' ',map("-w M$_:1GB:$numCoresPerMemoryDomain:1:$SMT", 0 ... $INFO{memoryDomainsPerNode}-1));
 | |
| print "Using: $exp\n";
 | |
| my $out =  `likwid-bench -t clload $exp`;
 | |
| foreach my $ln ( split("\n", $out) ){
 | |
|     if ( $ln =~ /MByte\/s:\s+([0-9.]+)/ ) {
 | |
|         $memBw = my $rounded = int($1/1000 + 0.5);
 | |
|     }
 | |
| }
 | |
| 
 | |
| my $flopsScalar;
 | |
| $out =  `likwid-bench -t peakflops -w N:24kB:$numCoresPerNode`;
 | |
| foreach my $ln ( split("\n", $out) ){
 | |
|     if ( $ln =~ /MFlops\/s:\s+([0-9.]+)/ ) {
 | |
|         $flopsScalar = my $rounded = int($1/1000 + 0.5);
 | |
|     }
 | |
| }
 | |
| 
 | |
| my $simd = "";
 | |
| my $fh;
 | |
| open($fh,"<","/proc/cpuinfo");
 | |
| foreach my $ln ( <$fh> ) {
 | |
|     if ( $ln =~ /flags/ ) {
 | |
|         if ( $ln =~ /avx2/ ) {
 | |
|             $simd = '_avx_fma';
 | |
|         }
 | |
|         if ( $ln =~ /avx512ifma/ ) {
 | |
|             $simd = '_avx512_fma';
 | |
|         }
 | |
|         last;
 | |
|     }
 | |
| }
 | |
| close $fh;
 | |
| 
 | |
| print "Using peakflops variant $simd\n";
 | |
| my $flopsSimd;
 | |
| $out =  `likwid-bench -t peakflops$simd -w N:500kB:$numCoresPerNode`;
 | |
| foreach my $ln ( split("\n", $out) ){
 | |
|     if ( $ln =~ /MFlops\/s:\s+([0-9.]+)/ ) {
 | |
|         $flopsSimd = my $rounded = int($1/1000 + 0.5);
 | |
|     }
 | |
| }
 | |
| 
 | |
| if ( $INFO{numGPUs} > 0 ) {
 | |
|     $INFO{gpus} = "\"accelerators\": [\n";
 | |
| 
 | |
|     my @gpuStr;
 | |
| 
 | |
|     foreach $id ( 0 ... ($INFO{numGPUs}-1) ) {
 | |
|         my %gpu = %{$DOMAINS{gpu}[$id]};
 | |
|         my $deviceAddr =  sprintf("%08x:%02x:%02x\.0", hex($gpu{domain}), hex($gpu{bus}), hex($gpu{device}));
 | |
|         $gpuStr[$id] = <<END
 | |
|      {
 | |
|             "id": "$deviceAddr",
 | |
|             "type": "$gpu{type}",
 | |
|              "model": "$gpu{model}"
 | |
|          }
 | |
| END
 | |
|     }
 | |
| 
 | |
|     $INFO{gpus} .= join(",\n",@gpuStr);
 | |
|     $INFO{gpus} .= "]\n";
 | |
| } else {
 | |
|     $INFO{gpus} = '';
 | |
| }
 | |
| 
 | |
| 
 | |
| print <<"END";
 | |
| {
 | |
|       "name": "<FILL IN>",
 | |
|       "processorType": "$INFO{processor}",
 | |
|       "socketsPerNode": $INFO{socketsPerNode},
 | |
|       "coresPerSocket": $INFO{coresPerSocket},
 | |
|       "threadsPerCore": $INFO{threadsPerCore},
 | |
|       "flopRateScalar": {
 | |
|            "unit": {
 | |
|                "base": "F/s",
 | |
|                "prefix": "G"
 | |
|            },
 | |
|            "value": $flopsScalar
 | |
|       },
 | |
|       "flopRateSimd": {
 | |
|            "unit": {
 | |
|                "base": "F/s",
 | |
|                "prefix": "G"
 | |
|            },
 | |
|            "value": $flopsSimd
 | |
|       },
 | |
|       "memoryBandwidth": {
 | |
|            "unit": {
 | |
|                "base": "B/s",
 | |
|                "prefix": "G"
 | |
|            },
 | |
|            "value": $memBw
 | |
|       },
 | |
|       "nodes": "<FILL IN NODE RANGES>",
 | |
|       "topology": {
 | |
|           "node": [$node],
 | |
|           "socket": [
 | |
|           $INFO{sockets}
 | |
|           ],
 | |
|           "memoryDomain": [
 | |
|           $INFO{memoryDomains}
 | |
|           ],
 | |
|           "core": [
 | |
|           $INFO{cores}
 | |
|           ]
 | |
|           $INFO{gpus}
 | |
|       }
 | |
| }
 | |
| END
 |