diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts
index 9cd215d98d478a456857b52f9f5c5388e1afa153..ccafd0717a18bf15ef74be23f33abae1c1a40f06 100644
--- a/app/modules/prover/lib/blockProver.ts
+++ b/app/modules/prover/lib/blockProver.ts
@@ -44,6 +44,9 @@ export class WorkerFarm {
     })
   }
 
+  get nbWorkers() {
+    return this.theEngine.getNbWorkers()
+  }
 
   changeCPU(cpu:any) {
     return this.theEngine.setConf({ cpu })
@@ -175,7 +178,6 @@ export class BlockProver {
       const start = Date.now();
       let result = await powFarm.askNewProof({
         newPoW: {
-          turnDuration: os.arch().match(/arm/) ? CommonConstants.POW_TURN_DURATION_ARM : CommonConstants.POW_TURN_DURATION_PC,
           conf: {
             cpu: this.conf.cpu,
             prefix: this.conf.prefix,
@@ -194,10 +196,10 @@ export class BlockProver {
         throw 'Proof-of-work computation canceled because block received';
       } else {
         const proof = result.block;
-        const testsCount = result.testsCount;
+        const testsCount = result.testsCount * powFarm.nbWorkers
         const duration = (Date.now() - start);
-        const testsPerSecond = (testsCount / (duration / 1000)).toFixed(2);
-        this.logger.info('Done: #%s, %s in %ss (%s tests, ~%s tests/s)', block.number, proof.hash, (duration / 1000).toFixed(2), testsCount, testsPerSecond);
+        const testsPerSecond = testsCount / (duration / 1000)
+        this.logger.info('Done: #%s, %s in %ss (~%s tests, ~%s tests/s, using %s cores, CPU %s%)', block.number, proof.hash, (duration / 1000).toFixed(2), testsCount, testsPerSecond.toFixed(2), powFarm.nbWorkers, Math.floor(100*this.conf.cpu))
         this.logger.info('FOUND proof-of-work with %s leading zeros followed by [0-' + highMark + ']!', nbZeros);
         return BlockDTO.fromJSONObject(proof)
       }
diff --git a/app/modules/prover/lib/engine.ts b/app/modules/prover/lib/engine.ts
index cc83f46822764786bf91c1c02156c597966cc299..30585270af6445ed0e0c7c9d59d17d40fbd92c32 100644
--- a/app/modules/prover/lib/engine.ts
+++ b/app/modules/prover/lib/engine.ts
@@ -1,4 +1,3 @@
-import {ProverConstants} from "./constants"
 import {Master as PowCluster} from "./powCluster"
 import {ConfDTO} from "../../../lib/dto/ConfDTO"
 
@@ -25,22 +24,25 @@ export class PowEngine {
     this.id = this.cluster.clusterId
   }
 
+  getNbWorkers() {
+    return this.cluster.nbWorkers
+  }
+
   forceInit() {
     return this.cluster.initCluster()
   }
 
   async prove(stuff:any) {
-
-    if (this.cluster.hasProofPending) {
-      await this.cluster.cancelWork()
-    }
-
-    const cpus = os.cpus()
-
-    if (os.arch().match(/arm/) || cpus[0].model.match(/Atom/)) {
-      stuff.newPoW.conf.nbCores /= 2; // Make sure that only once each physical core is used (for Hyperthreading).
-    }
-    return await this.cluster.proveByWorkers(stuff)
+        if (this.cluster.hasProofPending) {
+          await this.cluster.cancelWork()
+        }
+    
+        const cpus = os.cpus()
+    
+        if (os.arch().match(/arm/) || cpus[0].model.match(/Atom/)) {
+          stuff.newPoW.conf.nbCores /= 2; // Make sure that only once each physical core is used (for Hyperthreading).
+        }
+        return await this.cluster.proveByWorkers(stuff)
   }
 
   cancel() {
@@ -48,9 +50,6 @@ export class PowEngine {
   }
 
   setConf(value:any) {
-    if (os.arch().match(/arm/) && value.cpu !== undefined) {
-      value.cpu /= 2; // Don't know exactly why is ARM so much saturated by PoW, so let's divide by 2
-    }
     return this.cluster.changeConf(value)
   }
 
diff --git a/app/modules/prover/lib/powCluster.ts b/app/modules/prover/lib/powCluster.ts
index 4d4820777cb9b279aebea2d09680d1be0b3aab1f..140c887a5fa311e5d6ce1aec8f77d4fcb66c5052 100644
--- a/app/modules/prover/lib/powCluster.ts
+++ b/app/modules/prover/lib/powCluster.ts
@@ -195,7 +195,6 @@ export class Master {
             highMark: stuff.newPoW.highMark,
             pair: _.clone(stuff.newPoW.pair),
             forcedTime: stuff.newPoW.forcedTime,
-            turnDuration: stuff.newPoW.turnDuration,
             conf: {
               medianTimeBlocks: stuff.newPoW.conf.medianTimeBlocks,
               avgGenTime: stuff.newPoW.conf.avgGenTime,
diff --git a/app/modules/prover/lib/proof.ts b/app/modules/prover/lib/proof.ts
index 9b15c0be5aaff08b078c5dd495dbb0432be983ea..02927aac80c5750b1a23c391480d98ae257358c4 100644
--- a/app/modules/prover/lib/proof.ts
+++ b/app/modules/prover/lib/proof.ts
@@ -6,15 +6,11 @@ import {ProverConstants} from "./constants"
 import {KeyGen} from "../../../lib/common-libs/crypto/keyring"
 import {dos2unix} from "../../../lib/common-libs/dos2unix"
 import {rawer} from "../../../lib/common-libs/index"
+import {ProcessCpuProfiler} from "../../../ProcessCpuProfiler"
 
 const moment = require('moment');
 const querablep = require('querablep');
 
-const PAUSES_PER_TURN = 5;
-
-// This value can be changed
-let TURN_DURATION_IN_MILLISEC = 100;
-
 let computing = querablep(Promise.resolve(null));
 let askedStop = false;
 
@@ -90,7 +86,6 @@ function beginNewProofOfWork(stuff:any) {
       prefix *= 100 * ProverConstants.NONCE_RANGE
     }
     const highMark = stuff.highMark;
-    const turnDuration = stuff.turnDuration || TURN_DURATION_IN_MILLISEC
     let sigFunc = null;
     if (signatureFunc && lastSecret === pair.sec) {
       sigFunc = signatureFunc;
@@ -108,13 +103,17 @@ function beginNewProofOfWork(stuff:any) {
 
     let testsCount = 0;
     let found = false;
-    let score = 0;
     let turn = 0;
+    const profiler = new ProcessCpuProfiler(100)
+    let cpuUsage = profiler.cpuUsageOverLastMilliseconds(1)
+    // We limit the number of tests according to CPU usage
+    let testsPerRound = 1
+    let turnDuration = 20 // We initially goes quickly to the max speed = 50 reevaluations per second (1000 / 20)
 
     while (!found && !askedStop) {
 
       /*****************
-       * A TURN
+       * A TURN ~ 100ms
        ****************/
 
       await Promise.race([
@@ -125,26 +124,9 @@ function beginNewProofOfWork(stuff:any) {
         // II. Process the turn's PoW
         (async () => {
 
-          /*****************
-           * A TURN OF POW ~= 100ms by default
-           * --------------------
-           *
-           * The concept of "turn" is required to limit the CPU usage.
-           * We need a time reference to have the speed = nb tests / period of time.
-           * Here we have:
-           *
-           *   - speed = testsCount / turn
-           *
-           * We have taken 1 turn = 100ms to control the CPU usage after 100ms of PoW. This means that during the
-           * very first 100ms of the PoW, CPU usage = 100%. Then it becomes controlled to the %CPU set.
-           ****************/
-
             // Prove
           let i = 0;
           const thisTurn = turn;
-          const pausePeriod = score ? score / PAUSES_PER_TURN : 10; // number of pauses per turn
-          // We limit the number of tests according to CPU usage
-          const testsPerRound = score ? Math.floor(score * currentCPU) : 1000 * 1000 * 1000
 
           // Time is updated regularly during the proof
           block.time = getBlockTime(block, conf, forcedTime)
@@ -196,7 +178,7 @@ function beginNewProofOfWork(stuff:any) {
             if (!found && !askedStop) {
               i++;
               testsCount++;
-              if (i % pausePeriod === 0) {
+              if (i % testsPerRound === 0) {
                 await countDown(0); // Very low pause, just the time to process eventual end of the turn
               }
             }
@@ -208,12 +190,24 @@ function beginNewProofOfWork(stuff:any) {
           if (!found) {
 
             // CPU speed recording
-            if (turn > 0 && !score) {
-              score = testsCount;
+            if (turn > 0) {
+              const oldTestsPerRound = testsPerRound
+              cpuUsage = profiler.cpuUsageOverLastMilliseconds(turnDuration)
+              if (cpuUsage > currentCPU + 0.005 || cpuUsage < currentCPU - 0.005) {
+                let powVariationFactor
+                // powVariationFactor = currentCPU / (cpuUsage || 0.01) / 5 // divide by 2 to avoid extreme responses
+                if (currentCPU > cpuUsage) {
+                  powVariationFactor = 1.01
+                  testsPerRound = Math.max(1, Math.ceil(testsPerRound * powVariationFactor))
+                } else {
+                  powVariationFactor = 0.99
+                  testsPerRound = Math.max(1, Math.floor(testsPerRound * powVariationFactor))
+                }
+              }
             }
 
             /*****************
-             * UNLOAD CPU CHARGE
+             * UNLOAD CPU CHARGE FOR THIS TURN
              ****************/
             // We wait for a maximum time of `turnDuration`.
             // This will trigger the end of the turn by the concurrent race I. During that time, the proof.js script
@@ -226,6 +220,9 @@ function beginNewProofOfWork(stuff:any) {
 
       // Next turn
       turn++
+
+      turnDuration += 1
+      turnDuration = Math.min(turnDuration, 1000) // Max 1 second per turn
     }
 
     /*****************