Yup, it's completely normal for CPUs to throttle. What ends up happening is that, by default, only one core wants to be used -- this results in a higher clock speed and translates into more power consumption. By the same token, when multiple cores begin to be utilized, the CPU's frequency starts to vacillate in an odd fashion. If you understand multithreading programming concepts in C++, the following code will make sense to you:
(pulled from https://github.com/BOINC/boinc/blob/master/client/app.cpp , 9 September 2015)
Code:
// Initialize diagnostics framework for this thread
//
diagnostics_thread_init();
while (1) {
client_mutex.lock();
if (gstate.tasks_suspended
|| gstate.global_prefs.cpu_usage_limit > 99
|| gstate.global_prefs.cpu_usage_limit < 0.005
) {
client_mutex.unlock();
// ::Sleep((int)(1000*10)); // for Win debugging
boinc_sleep(10);
continue;
}
double on, off, on_frac = gstate.global_prefs.cpu_usage_limit / 100;
#if 0
// sub-second CPU throttling
#define THROTTLE_PERIOD 1.
on = THROTTLE_PERIOD * on_frac;
off = THROTTLE_PERIOD - on;
#else
// throttling w/ at least 1 sec between suspend/resume
if (on_frac > .5) {
off = 1;
on = on_frac/(1.-on_frac);
} else {
on = 1;
off = (1.-on_frac)/on_frac;
}
#endif
gstate.tasks_throttled = true;
gstate.active_tasks.suspend_all(SUSPEND_REASON_CPU_THROTTLE);
client_mutex.unlock();
boinc_sleep(off);
client_mutex.lock();
if (!gstate.tasks_suspended) {
gstate.active_tasks.unsuspend_all(SUSPEND_REASON_CPU_THROTTLE);
}
gstate.tasks_throttled = false;
client_mutex.unlock();
boinc_sleep(on);
}
return 0;
}
The code above comes from the BOINC client (linked above). While you can't see it here, per se, there are places in the code on their GitHub repository suggesting that sometimes a "soft" operation is used in place of an atomic operation. I suggest you download and build the client yourself, as doing this will allow you to tweak the build so that it runs better on your machine.