Имитация загрузки процессора при переполнении стека

В настоящее время я пишу приложение в Windows, используя C ++, и я хотел бы имитировать загрузку процессора.

У меня есть следующий код:

void task1(void *param) {

unsigned elapsed =0;
unsigned t0;

while(1){

if ((t0=clock())>=50+elapsed){//if time elapsed is 50ms

elapsed=t0;
Sleep(50);
}
}
}

int main(){

int ThreadNr;

for(int i=0; i < 4;i++){//for each core (i.e. 4 cores)
_beginthread( task1, 0, &ThreadNr );//create a new thread and run the "task1" function
}

while(1){}
}

Я написал этот код, используя ту же методологию, что и в ответах, приведенных в этой теме: Имитировать постоянную нагрузку на процессор и пики

Мои вопросы:

  1. Правильно ли я перевел код C # из другого поста на C ++?
  2. Будет ли этот код генерировать среднюю загрузку процессора в 50% на четырехъядерном процессоре?
  3. Как я могу с разумной точностью определить процент загрузки процессора? (диспетчер задач мой единственный вариант?)

РЕДАКТИРОВАТЬ: Причина, по которой я задаю этот вопрос, заключается в том, что я хочу, чтобы в конечном итоге я мог генерировать нагрузки на процессор в 10,20,30, …, 90% в разумных пределах. Этот код, кажется, хорошо работает для генерации нагрузки на 70%< но кажется очень неточным при любой нагрузке ниже 70% (как измерено показаниями загрузки ЦП менеджера задач).

Есть ли у кого-нибудь идеи относительно того, как я могу генерировать указанные нагрузки, но все же смогу использовать свою программу на разных компьютерах (то есть с разными процессорами)?

4

Решение

На первый взгляд, это выглядит не очень красиво, но правильно: C ++ или C (простой способ убедиться в этом — скомпилировать). Включения отсутствуют (<windows.h>, <process.h>, а также <time.h>) но в остальном он компилируется нормально.

Обратите внимание, что clock а также Sleep не очень точны, и Sleep не очень надежно либо. В среднем, функция потока должна работать как задумано, хотя (дать или взять несколько процентов вариации).

Тем не менее, что касается вопроса 2) вы должны заменить последний while(1){} с чем-то, что блокирует, а не вращает (например, WaitForSingleObject или же Sleep если вы будете). в противном случае вся программа будет не 50% нагрузки на квадрок У вас будет 100% нагрузки на одно ядро ​​из-за основного потока, плюс 4x 50% от ваших четырех рабочих. Это, очевидно, в сумме составит более 50% на ядро ​​(и приведет к тому, что потоки отскочат от одного ядра к другому, что приведет к неприятным побочным эффектам).

Использование диспетчера задач или аналогичной утилиты для проверки того, получаете ли вы нужную нагрузку, является хорошим вариантом (и поскольку простой решение, это также лучший).

Также обратите внимание, что моделирование нагрузки таким образом будет наверное вид работы, но не на 100% надежный.
Могут быть эффекты (память, исполнительные блоки), которые трудно предсказать. Предположим, например, что вы используете 100% целочисленных исполнительных блоков ЦП с этим циклом (разумное предположение), но ноль его единиц с плавающей запятой или SSE. Современные процессоры могут распределять ресурсы между реальными или логическими ядрами, и вы не сможете точно предсказать, какие эффекты вы получите. Или другой поток может быть связан с памятью или иметь значительные сбои страниц, поэтому отнимаемое процессорное время не повлияет на него так сильно, как вы думаете (на самом деле может дать достаточно времени, чтобы предварительная выборка работала лучше). Или это может заблокировать передачу AGP. Или что-то еще, что вы не можете сказать.

РЕДАКТИРОВАТЬ:

Улучшенная версия, более короткий код, который исправляет несколько проблем, а также работает как задумано:

  • Пользы clock_t для значения, возвращаемого clock (что технически «более правильно», чем использование не специально typedefцелое число Кстати, это, вероятно, та самая причина, по которой оригинальный код не работает так, как задумано, поскольку clock_t это подписанный целое число под Win32. Состояние в if() всегда оценивает trueпоэтому рабочие спят почти все время, не потребляя ресурсов процессора.
  • Меньше кода, менее сложная математика при вращении. Вычисляет время пробуждения 50 тиков в будущем и вращается до тех пор, пока это время не будет достигнуто.
  • Пользы getchar заблокировать программу в конце. Это не сжигает процессорное время и позволяет завершить программу, нажав Войти. Потоки не заканчиваются должным образом, как обычно, но в этом простом случае, вероятно, можно просто позволить ОС прекратить их при выходе из процесса.
  • Как и оригинальный код, это предполагает, что clock а также Sleep используйте те же галочки. По общему признанию, это смелое предположение, но оно справедливо для Win32, который вы использовали в исходном коде (обе «галочки» — миллисекунды). С ++ не имеет ничего подобного Sleep (без boost::threadили C ++ 11 std::thread), поэтому, если предполагается переносимость не в Windows, вам все равно придется переосмыслить.
  • Как и оригинальный код, он опирается на функции (clock а также Sleep) которые являются неточными и ненадежными. Sleep(50) равняется Sleep(63) в моей системе без использования timeBeginPeriod, Тем не менее, программа работает «почти идеально», что приводит к 50% +/- 0,5% нагрузки на мою машину.
  • Как и в исходном коде, здесь не учитываются приоритеты потоков. Процесс, который имеет класс приоритета выше, чем обычно, не будет впечатлен этим кодом регулирования, потому что так работает планировщик Windows.

    #include <windows.h>
    #include <process.h>
    #include <time.h>
    #include <stdio.h>void task1(void *)
    {
    while(1)
    {
    clock_t wakeup = clock() + 50;
    while(clock() < wakeup) {}
    Sleep(50);
    }
    }
    
    int main(int, char**)
    {
    int ThreadNr;
    for(int i=0; i < 4; i++) _beginthread( task1, 0, &ThreadNr );
    
    (void) getchar();
    return 0;
    }
    
6

Другие решения

Вы можете использовать Windows API счетчика перфорирования чтобы получить нагрузку на процессор. Либо для всей системы, либо для вашего процесса.

1

Вот пример кода, который загрузил мой процессор до 100% в Windows.

#include "windows.h"
DWORD WINAPI thread_function(void* data)
{
float number = 1.5;
while(true)
{
number*=number;
}
return 0;
}

void main()
{
while (true)
{
CreateThread(NULL, 0, &thread_function, NULL, 0, NULL);
}
}

Когда вы создадите приложение и запустите его, нажмите Ctrl-C, чтобы убить приложение.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector