Тестирование энергоэффективности и скорости вычислений видеокарт для майнинга в BOINC проектах

Рисунок 1 - Пример кода калькулятора
На момент написания статьи идет криптозима (весна 2025 года). Количество предложений видеокарт от майнеров на популярных площадках увеличивается, и сейчас неплохое время для апгрейда оборудования. Материал этой статьи будет полезен для сравнения характеристик видеокарт для майнинга в проектах распределенных вычислений на платформе BOINC. Подробно о добровольных вычислениях и проектах можно почитать здесь: https://ru.wikipedia.org/wiki/Добровольные_вычисления https://ru.wikipedia.org/wiki/BOINC Характеристики графических процессоров, которые будут протестированы, приведены в таблице 1. Данные для таблицы взяты с сайта techpowerup.com, как показали эксперименты в реальности тактовая частота работы графических процессоров отличается от приведенной в открытых источниках. Также по графическому процессору CMP 90HX в таблице завышен показатель TDP, как показали замеры, энергопотребление ограничено мощностью 250 Вт. Возможно попался экземпляр с модифицированным биосом.
Название процессора | Nvidia CMP 170HX (GA100-105F-A1) | |||
Nvidia P102-100 (GP102-100-A1) | ||||
Nvidia 1080ti Duke (GP102-350-K1-A1) | ||||
Nvidia CMP 90HX (GA102-100-A1) | ||||
Архитектура | Ampere | Pascal | Pascal | Ampere |
Технологический процесс производства, нм | 7 | 16 | 16 | 8 |
Унифицированных шейдерных процессоров, шт | 4480 | 3200 | 3584 | 6400 |
Текстурных блоков, шт | 280 | 200 | 224 | 200 |
Блоков растеризации, шт | 128 | 80 | 88 | 80 |
Потоковых мультипроцессоров, шт | 70 | 25 | 28 | 50 |
Ядра Tensor, шт | 280 | 0 | 0 | 200 |
Тактовая частота номинальная, МГц | 1140 | 1582 | 1481 | 1500 |
Тактовая частота максимальная, МГц | 1410 | 1683 | 1582 | 1710 |
Пропускная способность памяти, ГБ/с | 2900 | 440,3 | 484,4 | 760,3 |
Производительность FP16 (половинной точности), TFLOPS | 50,530 | 0,1683 | 0,1772 | 21,89 |
Производительность FP32 (одинарной точности), TFLOPS | 12,630 | 10,77 | 11,34 | 21,89 |
Производительность FP64 (двойной точности), TFLOPS | 6,317 | 0,3366 | 0,3544 | 0,342 |
Требования по теплоотводу, TDP, Вт | 250 | 250 | 250 | 320 |
POST - скрытый метод отправки данных на сервер. Метод POST передает информацию через HTTP-заголовки. Информация кодируется, как описано в случае метода GET, и помещается в заголовок QUERY_STRING. Метод POST не имеет ограничений по объему отправляемых данных. Метод POST может использоваться для отправки ASCII, а также двоичных данных.
Создаем отдельный файл, который будет принимать выбранные параметры из формы, заполненные пользователем. Так как данные из формы будут передаваться массивом, мы в нём и создадим переменные для хранения суммы и вывода расчетов пользователю.
$data - переменная, в которую записываем все данные, полученные методом POST.Запишем условия проверки данных, все ли они передались и нет ли пустых значений:
//Условие при отправке запроса //Если запрос пуст if (empty($_POST)) { echo $errors[] = 'Данные не отправлены!'; } if (!empty($_POST)): $data = $_POST; $errors[] = ''; if (!empty($data['top_lotok']) AND $data['top_lotok'] == 1): $top_true = 1; endif; if (!empty($data['type_lotok'])): $type = $connect->query('SELECT * FROM view_lotok WHERE id_views='.$data['type_lotok']); $type = mysqli_fetch_Array($type); else: $errors[] = 'Тип лотка не определён или выбраны неверные значения!'; endif; if (!empty($data['kolvo_uglov']) OR isset($data['kolvo_uglov'])): $kolvo_uglov = $data['kolvo_uglov']; elseif ($data['kolvo_uglov'] == 0): $kolvo_uglov = 0; else: $errors[] = 'Количество углов не введено!'; endif; if (!empty($data['length_line'])): $length = intval($data['length_line']); else: $errors[] = 'Длина прямых участков не указана!'; endif; if (!empty($data['width_lotka'])): $width = $connect->query('SELECT * FROM width_lotok WHERE id_width='.$data['width_lotka']); $width = mysqli_fetch_array($width); else: $errors[] = 'Ширина лотка не выбрана или по данной ширине нет лотков!'; endif; if (!empty($data['height_lotka'])): $height = $connect->query('SELECT * FROM height_lotok WHERE id_height='.$data['height_lotka']); $height = mysqli_fetch_array($height); else: $errors[] = 'Высота лотка не выбрана или по данной высоте нет лотков!'; endif; if (!empty($height) and !empty($width)): $lotok = $connect->query('SELECT * FROM lotok WHERE id_height=''.$height['id_height'].'' AND id_width=''.$width['id_width'].'' AND id_views=''.$type['id_views'].'''); $lotok = mysqli_fetch_array($lotok); else: $errors[] = 'С такими данными лоток не найден!'; endif; $cost = 0; // Проверка выбора покрытия if ($lotok == '' OR !$lotok OR empty($lotok) OR $lotok == null): $errors[] = 'Лоток не найден с такими параметрами!'; else: $cost = 'Измените данные для расчета!'; if ($data['pokryitie_lotka'] == 'hot'): $cost = $lotok['lotok_cost_procreator']; else: $cost = $lotok['lotok_cost_etm']; endif; endif; // Проверка длины прямых углов и добавление до кратности 3м if ($length % 3 == 0 or $length == 3) { $cost = $cost * $length; } else if ($length == 1) { $length = $length + 2; $cost = $cost * $length; } else if ($length % 2 == 0) { $length = $length + 1; $cost = $cost * $length; }
Запишем формулы расчетов сумм:
// Расчёт стоимости работ
$sto_rabot = ($length * 1000) + (1500 * $kolvo_uglov)
где
$length - длина прямых участков (м)
$kolvo_uglov - количество углов
// Сумма углов
$cost_cap = $kolvo_uglov * $data[‘cost_cap’]
Общая сумма без крышки:
// Сумма заказа
$summa = $cost + $sto_rabot + $cost_cap
где
$cost - цена лотка
$cost_cap - сумма углов
Общая сумма при наличии крышки:
$summa = $cost + $sto_rabot + ($top['cost_etm'] * $length) + $cost_cap;
где
$top - массив данных о крышке, подходящей по ширине и высоте к лотку.
Также если пользователь выбрал “горячее цинкование” то берутся записи цен с названием столбца “cost_procreator”, иначе берутся цены “'cost_etm”.
Код обработки данных и подсчетов:
// Расчёт стоимости работ $sto_rabot = ($length * 1000) + (1500 * $kolvo_uglov); if ($kolvo_uglov != 0): $cap = $connect->query('SELECT * FROM cap_lotok'); $cap = mysqli_fetch_array($cap); if ($data['pokryitie_lotka'] == 'hot'): $cost_cap = $cap['cost_etm'] * $kolvo_uglov; else: $cost_cap = $cap['cost_procreator'] * $kolvo_uglov; endif; else: $cost_cap = 0; endif; // Сумма заказа $summa = $cost + $sto_rabot + $cost_cap; //Проверка наличия крышки и расчет суммы при её наличии if ($data['top_lotok'] == 1 AND !empty($data['top_lotok'])) { $top = $connect->query('SELECT * FROM top_lotok WHERE top_lotok.width_top='.$width['id_width'].' OR top_lotok.height_top='.$height['id_height']); $top = mysqli_fetch_array($top); $top_cost = $top['cost_etm']; if ($data['pokryitie_lotka'] == 'hot'): $summa = $cost + $sto_rabot + ($top['cost_procreator'] * $length) + $cost_cap; $top_cost = $top['cost_procreator']; else: $summa = $cost + $sto_rabot + ($top['cost_etm'] * $length) + $cost_cap; $top_cost = $top['cost_etm']; endif; } endif;
Результат получаем в виде блока Html:
if (!empty($errors)): <div class='promtex-error'> <strong style='color: red; text-align: center; display: block; width: 100%;'> <?php echo array_shift($errors); </strong> </div> endif; <span class='font-weight: bold; text-align:center; margin-bottom: 10px;'>Спецификация</span> <span><strong>Тип лотка: </strong><? echo $type['name_view'] ?></span> <span><strong>Длина прямых участков (м): </strong><? echo $length; ?></span> if (!empty($top)): <span><strong> Наличие крышки: </strong> Есть </span> endif; <span><strong>Наличие углов: </strong> // Проверка количества и наличия углов if (!empty($cap) OR isset($cap) AND $cap != 0): echo 'Есть'; else: echo 'Нет'; endif; </span> <span><strong>Сумма работ: </strong> echo $sto_rabot .' руб'; </span> <span><strong>Общая сумма: </strong> echo $summa.' руб'; </span> ';