Passed
Pull Request — master (#4354)
by David
11:22
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, NVIDIA, etc.
30
// This avoids showing the same model twice
31
//
32
function strip_vendor($model) {
33
    foreach (array("AMD ", "NVIDIA ", "ATI ", "Intel(R) ") as $maker) {
34
        $n = strlen($maker);
35
        if (substr($model, 0, $n) == $maker) {
36
            return substr($model, $n);
37
        }
38
    }
39
    return $model;
40
}
41
42
// take a host.serialnum field (which may encode several GPUs)
43
// and extract the model name for the given vendor
44
//
45
function get_gpu_model($x, $vendor) {
46
    $descs = explode("]", $x);
47
    array_pop($descs);
48
    foreach ($descs as $desc) {
49
        $desc = trim($desc, "[");
50
        $d = explode("|", $desc);
51
        if ($d[0] == "BOINC") continue;
52
        if ($d[0] != $vendor) continue;
53
        return strip_vendor(trim($d[1]));
54
    }
55
    return null;
56
}
57
58
function add_model($model, $r, $wu, &$models) {
59
    if (array_key_exists($model, $models)) {
60
        $models[$model]->count++;
61
        $models[$model]->time += $r->elapsed_time/$wu->rsc_fpops_est;
62
    } else {
63
        $x = new StdClass;
64
        $x->count = 1;
65
        $x->time = $r->elapsed_time/$wu->rsc_fpops_est;
66
        $models[$model] = $x;
67
    }
68
}
69
70
// return a data structure containing GPU usage info for a vendor
71
// $x->total: combined list
72
// $x->windows
73
// $x->linux
74
// $x->mac
75
//
76
function get_gpu_list($vendor, $alt_vendor=null) {
77
    $clause = "plan_class like '%$vendor%'";
78
    if ($alt_vendor) {
79
        $clause .= " or plan_class like '%$alt_vendor%'";
80
    }
81
    $avs = BoincAppVersion::enum($clause);
82
    if (count($avs) == 0) {
83
        $x = new StdClass;
84
        $x->total = array();
85
        return $x;
86
    }
87
88
    $av_ids = "";
89
    foreach($avs as $av) {
90
        $av_ids .= "$av->id, ";
91
    }
92
    if ($vendor == "cuda") {
93
        $av_ids .= "-3";
94
    } else if ($vendor == "ati") {
95
        $av_ids .= "-4";
96
    } else if ($vendor == "intel_gpu") {
97
        $av_ids .= "-5";
98
    } else {
99
        $av_ids .= "0";
100
    }
101
102
    $t = time() - 30*86400;
103
    //echo "start enum $vendor $av_ids\n";
104
    $results = BoincResult::enum(
105
        "app_version_id in ($av_ids) and create_time > $t and elapsed_time>100 limit 2000"
106
    );
107
    //echo "end enum\n";
108
    $total = array();
109
    $win = array();
110
    $linux = array();
111
    $mac = array();
112
    foreach ($results as $r) {
113
        $h = BoincHost::lookup_id($r->hostid);
114
        if (!$h) continue;
115
        $wu = BoincWorkunit::lookup_id($r->workunitid);
116
        if (!$wu) continue;
117
        $v = "";
118
        if ($vendor == "cuda") {
119
            $v = "CUDA";
120
        } else if ($vendor == "intel_gpu") {
121
            $v = "INTEL";
122
        } else {
123
            $v = "CAL";
124
        }
125
        $model = get_gpu_model($h->serialnum, $v);
126
        if (!$model) continue;
127
        add_model($model, $r, $wu, $total);
128
        if (strstr($h->os_name, "Windows")) {
129
            add_model($model, $r, $wu, $win);
130
        }
131
        if (strstr($h->os_name, "Linux")) {
132
            add_model($model, $r, $wu, $linux);
133
        }
134
        if (strstr($h->os_name, "Darwin")) {
135
            add_model($model, $r, $wu, $mac);
136
        }
137
138
    }
139
    $x = new StdClass;
140
    $x->total = $total;
141
    $x->win = $win;
142
    $x->linux = $linux;
143
    $x->mac = $mac;
144
    return $x;
145
}
146
147
function get_gpu_lists() {
148
    $x = new StdClass;
149
    $x->cuda = get_gpu_list("cuda", "nvidia");
150
    $x->ati = get_gpu_list("ati", "amd");
151
    $x->intel_gpu = get_gpu_list("intel_gpu");
152
    $x->time = time();
153
    return $x;
154
}
155
156
function gpucmp($x1, $x2) {
157
    return $x1->avg_time > $x2->avg_time;
158
}
159
160
function show_list($models, $name) {
161
    echo "<td><h2>$name</h2>\n";
162
    if (!count($models)) {
163
        echo tra("No GPU tasks reported")."</td>\n";
164
        return;
165
    }
166
    $max_count = 0;
167
    foreach ($models as $model=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
168
        if ($x->count > $max_count) $max_count = $x->count;
169
        $x->avg_time = $x->time/$x->count;
170
    }
171
    $min_time = 1e9;
172
    foreach ($models as $model=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
173
        if ($x->count < $max_count/10) continue;
174
        if ($x->avg_time < $min_time) $min_time = $x->avg_time;
175
    }
176
    uasort($models, 'gpucmp');
177
    echo "<ol>\n";
178
    foreach ($models as $model=>$x) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "=>"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space before "=>"; 0 found
Loading history...
179
        if ($x->count < $max_count/10) continue;
180
        $s = number_format($min_time/$x->avg_time, 3);
181
        echo "<li>($s)  $model\n";
182
    }
183
    echo "</ol></td>\n";
184
}
185
186
function show_vendor($vendor, $x) {
187
    echo "<h2>$vendor</h2>\n";
188
    if (!count($x->total)) {
189
        echo tra("No GPU tasks reported");
190
        return;
191
    }
192
    $have_win = count($x->win)>0;
193
    $have_mac = count($x->mac)>0;
194
    $have_linux = count($x->linux)>0;
195
    $n = 0;
196
    if ($have_win) $n++;
197
    if ($have_mac) $n++;
198
    if ($have_linux) $n++;
199
    $show_total = $n>1;
200
    start_table();
201
    echo "<tr>";
202
    if ($show_total) {
203
        show_list($x->total, "Total");
204
    }
205
    show_list($x->win, "Windows");
206
    show_list($x->linux, "Linux");
207
    show_list($x->mac, "Mac");
208
    echo "</tr></table>\n";
209
}
210
211
$d = get_cached_data(86400);
212
$data = FALSE;
213
if ($d) {
214
    $data = unserialize($d);
215
}
216
217
if (!$data) {
218
    $data = get_gpu_lists();
219
    set_cached_data(86400, serialize($data));
220
}
221
222
page_head(tra("Top GPU models"));
223
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.");
224
show_vendor("NVIDIA", $data->cuda);
225
show_vendor("ATI/AMD", $data->ati);
226
show_vendor("Intel", $data->intel_gpu);
227
echo "<p>Generated ".time_str($data->time);
228
page_tail();
229
230
?>
231