Passed
Pull Request — master (#4354)
by David
10:55
created

strip_vendor()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 8
rs 10
1
<?php
2
3
// This file is part of BOINC.
4
// http://boinc.berkeley.edu
5
// Copyright (C) 2011 University of California
6
//
7
// BOINC is free software; you can redistribute it and/or modify it
8
// under the terms of the GNU Lesser General Public License
9
// as published by the Free Software Foundation,
10
// either version 3 of the License, or (at your option) any later version.
11
//
12
// BOINC is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
// See the GNU Lesser General Public License for more details.
16
//
17
// You should have received a copy of the GNU Lesser General Public License
18
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
19
20
// generate a page of the best-performing GPU models.
21
//
22
// "best-performing" is defined as minimizing the average of
23
//
24
// elapsed_time(J)/rsc_fpops_est(J)
25
// over completed jobs J currently in the DB
26
27
require_once("../inc/util.inc");
28
29
// strip leading AMD or NVIDIA
30
//
31
function strip_vendor($model) {
32
    foreach (array("AMD ", "NVIDIA ") as $maker) {
33
        $n = strlen($maker);
34
        if (substr($model, 0, $n) == $maker) {
35
            return substr($model, $n);
36
        }
37
    }
38
    return $model;
39
}
40
41
// take a host.serialnum field (which may encode several GPUs)
42
// and extract the model name for the given vendor
43
//
44
function get_gpu_model($x, $vendor) {
45
    $descs = explode("]", $x);
46
    array_pop($descs);
47
    foreach ($descs as $desc) {
48
        $desc = trim($desc, "[");
49
        $d = explode("|", $desc);
50
        if ($d[0] == "BOINC") continue;
51
        if ($d[0] != $vendor) continue;
52
        return strip_vendor(trim($d[1]));
53
    }
54
    return null;
55
}
56
57
function add_model($model, $r, $wu, &$models) {
58
    if (array_key_exists($model, $models)) {
59
        $models[$model]->count++;
60
        $models[$model]->time += $r->elapsed_time/$wu->rsc_fpops_est;
61
    } else {
62
        $x = new StdClass;
63
        $x->count = 1;
64
        $x->time = $r->elapsed_time/$wu->rsc_fpops_est;
65
        $models[$model] = $x;
66
    }
67
}
68
69
// return a data structure containing GPU usage info for a vendor
70
// $x->total: combined list
71
// $x->windows
72
// $x->linux
73
// $x->mac
74
//
75
function get_gpu_list($vendor, $alt_vendor=null) {
76
    $clause = "plan_class like '%$vendor%'";
77
    if ($alt_vendor) {
78
        $clause .= " or plan_class like '%$alt_vendor%'";
79
    }
80
    $avs = BoincAppVersion::enum($clause);
81
    if (count($avs) == 0) {
82
        $x = new StdClass;
83
        $x->total = array();
84
        return $x;
85
    }
86
87
    $av_ids = "";
88
    foreach($avs as $av) {
89
        $av_ids .= "$av->id, ";
90
    }
91
    if ($vendor == "cuda") {
92
        $av_ids .= "-3";
93
    } else if ($vendor == "ati") {
94
        $av_ids .= "-4";
95
    } else if ($vendor == "intel_gpu") {
96
        $av_ids .= "-5";
97
    } else {
98
        $av_ids .= "0";
99
    }
100
101
    $t = time() - 30*86400;
102
    //echo "start enum $vendor $av_ids\n";
103
    $results = BoincResult::enum(
104
        "app_version_id in ($av_ids) and create_time > $t and elapsed_time>100 limit 2000"
105
    );
106
    //echo "end enum\n";
107
    $total = array();
108
    $win = array();
109
    $linux = array();
110
    $mac = array();
111
    foreach ($results as $r) {
112
        $h = BoincHost::lookup_id($r->hostid);
113
        if (!$h) continue;
114
        $wu = BoincWorkunit::lookup_id($r->workunitid);
115
        if (!$wu) continue;
116
        $v = "";
117
        if ($vendor == "cuda") {
118
            $v = "CUDA";
119
        } else if ($vendor == "intel_gpu") {
120
            $v = "INTEL";
121
        } else {
122
            $v = "CAL";
123
        }
124
        $model = get_gpu_model($h->serialnum, $v);
125
        if (!$model) continue;
126
        add_model($model, $r, $wu, $total);
127
        if (strstr($h->os_name, "Windows")) {
128
            add_model($model, $r, $wu, $win);
129
        }
130
        if (strstr($h->os_name, "Linux")) {
131
            add_model($model, $r, $wu, $linux);
132
        }
133
        if (strstr($h->os_name, "Darwin")) {
134
            add_model($model, $r, $wu, $mac);
135
        }
136
137
    }
138
    $x = new StdClass;
139
    $x->total = $total;
140
    $x->win = $win;
141
    $x->linux = $linux;
142
    $x->mac = $mac;
143
    return $x;
144
}
145
146
function get_gpu_lists() {
147
    $x = new StdClass;
148
    $x->cuda = get_gpu_list("cuda", "nvidia");
149
    $x->ati = get_gpu_list("ati", "amd");
150
    $x->intel_gpu = get_gpu_list("intel_gpu");
151
    $x->time = time();
152
    return $x;
153
}
154
155
function gpucmp($x1, $x2) {
156
    return $x1->avg_time > $x2->avg_time;
157
}
158
159
function show_list($models, $name) {
160
    echo "<td><h2>$name</h2>\n";
161
    if (!count($models)) {
162
        echo tra("No GPU tasks reported")."</td>\n";
163
        return;
164
    }
165
    $max_count = 0;
166
    foreach ($models as $model=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
167
        if ($x->count > $max_count) $max_count = $x->count;
168
        $x->avg_time = $x->time/$x->count;
169
    }
170
    $min_time = 1e9;
171
    foreach ($models as $model=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
172
        if ($x->count < $max_count/10) continue;
173
        if ($x->avg_time < $min_time) $min_time = $x->avg_time;
174
    }
175
    uasort($models, 'gpucmp');
176
    echo "<ol>\n";
177
    foreach ($models as $model=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
178
        if ($x->count < $max_count/10) continue;
179
        $s = number_format($min_time/$x->avg_time, 3);
180
        echo "<li>($s)  $model\n";
181
    }
182
    echo "</ol></td>\n";
183
}
184
185
function show_vendor($vendor, $x) {
186
    echo "<h2>$vendor</h2>\n";
187
    if (!count($x->total)) {
188
        echo tra("No GPU tasks reported");
189
        return;
190
    }
191
    $have_win = count($x->win)>0;
192
    $have_mac = count($x->mac)>0;
193
    $have_linux = count($x->linux)>0;
194
    $n = 0;
195
    if ($have_win) $n++;
196
    if ($have_mac) $n++;
197
    if ($have_linux) $n++;
198
    $show_total = $n>1;
199
    start_table();
200
    echo "<tr>";
201
    if ($show_total) {
202
        show_list($x->total, "Total");
203
    }
204
    show_list($x->win, "Windows");
205
    show_list($x->linux, "Linux");
206
    show_list($x->mac, "Mac");
207
    echo "</tr></table>\n";
208
}
209
210
$d = get_cached_data(86400);
211
$data = FALSE;
212
if ($d) {
213
    $data = unserialize($d);
214
}
215
216
if (!$data) {
217
    $data = get_gpu_lists();
218
    set_cached_data(86400, serialize($data));
219
}
220
221
page_head(tra("Top GPU models"));
222
echo tra("The following lists show the most productive GPU models on different platforms.  Relative speeds, measured by average elapsed time of tasks, are shown in parentheses.");
223
show_vendor("NVIDIA", $data->cuda);
224
show_vendor("ATI/AMD", $data->ati);
225
show_vendor("Intel", $data->intel_gpu);
226
echo "<p>Generated ".time_str($data->time);
227
page_tail();
228
229
?>
230