Browse Source

DynClk: Improve commented documentation

Luke Dashjr 12 years ago
parent
commit
6ecd69e56e
2 changed files with 46 additions and 6 deletions
  1. 23 2
      dynclock.c
  2. 23 4
      dynclock.h

+ 23 - 2
dynclock.c

@@ -16,6 +16,7 @@
 void dclk_prepare(struct dclk_data *data)
 {
 	*data = (struct dclk_data){
+		// after 275 sample periods
 		.minGoodSamples = 150.,
 	};
 }
@@ -47,28 +48,44 @@ bool dclk_updateFreq(struct dclk_data *data, dclk_change_clock_func_t changecloc
 			data->maxErrorRate[i + 1] = data->maxErrorRate[i] * (1.0 + 20.0 / i);
 
 	maxM = 0;
+	// Use max mulitplier up to the default as far as possible without hitting the max error rate
 	while (maxM < freqMDefault && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE)
 		maxM++;
+	// Use max mulitplier beyond the default if it's never hit the max error rate, and our current max has collected sufficient samples
 	while (maxM < data->freqMaxM && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE && data->errorWeight[maxM] >= data->minGoodSamples)
 		maxM++;
 
+	// Find the multiplier that gives the best hashrate
 	bestM = 0;
 	bestR = 0;
 	for (i = 0; i <= maxM; i++) {
-		r = (i + 1 + (i == data->freqM? DCLK_ERRORHYSTERESIS: 0)) * (1 - data->maxErrorRate[i]);
+		// Hashrate is weighed on a linear scale
+		r = (i + 1);
+		
+		// The currently selected frequency gets a small "bonus" in comparison, as hysteresis
+		if (i == data->freqM)
+			r += DCLK_ERRORHYSTERESIS;
+		
+		// Adjust for measured error rate
+		r *= (1 - data->maxErrorRate[i]);
+		
+		// If it beats the current best, update best*
 		if (r > bestR) {
 			bestM = i;
 			bestR = r;
 		}
 	}
 
+	// Actually change the clock if the best multiplier is not currently selected
 	if (bestM != data->freqM) {
 		rv = changeclock(thr, bestM);
 	}
 
+	// Find the highest multiplier that we've taken a reasonable sampling of
 	maxM = freqMDefault;
 	while (maxM < data->freqMaxM && data->errorWeight[maxM + 1] > 100)
 		maxM++;
+	// If the new multiplier is some fraction of the highest we've used long enough to get a good sample, assume there is something wrong and instruct the driver to shut it off
 	if ((bestM < (1.0 - DCLK_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) {
 		applog(LOG_ERR, "%"PRIpreprv": frequency drop of %.1f%% detect. This may be caused by overheating. FPGA is shut down to prevent damage.",
 		       cgpu->proc_repr,
@@ -91,7 +108,11 @@ void dclk_errorCount(struct dclk_data *data, double portion)
 
 void dclk_preUpdate(struct dclk_data *data)
 {
-	data->errorRate[data->freqM] = data->errorCount[data->freqM] / data->errorWeight[data->freqM] * (data->errorWeight[data->freqM] < 100 ? data->errorWeight[data->freqM] * 0.01 : 1.0);
+	data->errorRate[data->freqM] = data->errorCount[data->freqM] / data->errorWeight[data->freqM];
+	// errorWeight 100 begins after sample period 137; before then, we minimize the effect of measured errorRate
+	if (data->errorWeight[data->freqM] < 100)
+		data->errorRate[data->freqM] /= 100;
+	
 	if (data->errorRate[data->freqM] > data->maxErrorRate[data->freqM])
 		data->maxErrorRate[data->freqM] = data->errorRate[data->freqM];
 }

+ 23 - 4
dynclock.h

@@ -11,31 +11,50 @@ struct thr_info;
 #define DCLK_OVERHEATTHRESHOLD 0.4
 
 struct dclk_data {
+	// Current frequency multiplier
 	uint8_t freqM;
+	
+	// Maximum frequency multiplier to consider (set by driver)
 	uint8_t freqMaxM;
+	
+	// "Default" frequency multiplier to work with (set by driver)
 	uint8_t freqMDefault;
 
+	// Threshold before errorWeight is considered reasonably constant
+	// NOTE: This is not a mere number of sampling periods (but related)
 	uint8_t minGoodSamples;
 
+	// Numerator of errorWeight after dclk_errorCount
 	double errorCount[256];
+	
+	// Approaches 200
 	double errorWeight[256];
+	
+	// Error rate (0.0 - 1.0) as of end of last sampling period
 	double errorRate[256];
+	
+	// Highest error rate (0.0 - 1.0) encountered
 	double maxErrorRate[256];
 };
 
 typedef bool (*dclk_change_clock_func_t)(struct thr_info *, int multiplier);
 
+// Standard applog message called by driver frequency-change functions
 extern void dclk_msg_freqchange(const char *, int oldFreq, int newFreq, const char *tail);
 
 // Called to initialize dclk_data at startup
 extern void dclk_prepare(struct dclk_data *data);
-// Called for every quarter of a second to age error rate info
+
+// Called to start a sampling period
 extern void dclk_gotNonces(struct dclk_data *);
-// Called for errors (1.0 "portion" is a quarter second)
+
+// Called to increment the current sampling period's error rate (1.0 "portion" is 100% errors)
 extern void dclk_errorCount(struct dclk_data *, double portion);
-// Called after a nonce range is completed to update actual error rate
+
+// Called after a sampling period is completed to update actual error rate
 extern void dclk_preUpdate(struct dclk_data *data);
-// Called after a nonce range is completed, and error rate updated, to make actual clock adjustments
+
+// Called after a sampling period is completed, and error rate updated, to make actual clock adjustments
 extern bool dclk_updateFreq(struct dclk_data *, dclk_change_clock_func_t changeclock, struct thr_info *);
 
 #endif