/// <summary> /// Calculate the number of threads used when running a sieve. /// </summary> /// <param name="sieve">The sieve that was run.</param> /// <param name="settings">The run settings.</param> /// <returns>Returns a tuple of external threads used (each one running one sieve) and internal threads used (how many threads each sieve uses).</returns> private static (int thraeds, int pThreads) GetThreadCount(ISieveRunner sieve, SettingsV2 settings) { int threads = 1; if (settings.MultiThreaded) { threads = settings.ThreadCount == 0 ? Environment.ProcessorCount : settings.ThreadCount; } int pThreads = 1; if (sieve.IsParallel) { pThreads = settings.PThreadCount == 0 ? Environment.ProcessorCount : settings.PThreadCount; } return(threads, pThreads); }
/// <summary> /// Print the final output to the console. /// </summary> /// <param name="sieve">The sieve that was run.</param> /// <param name="passes">How many times it was run.</param> /// <param name="watch">The stopwatch used to time it.</param> /// <param name="settings">The settings that were in effect.</param> private static void PrintResults(ISieveRunner sieve, int passes, Stopwatch watch, SettingsV2 settings) { if (settings.Verbose) { string listing = sieve.GetFoundPrimes() .Select(a => a.ToString()) .Aggregate((a, b) => $"{a}, {b}"); Console.WriteLine(listing); Console.WriteLine(); } (int threads, int pThreads) = GetThreadCount(sieve, settings); Console.WriteLine(GetLongOutputDescription(sieve, passes, watch, threads, pThreads)); Console.WriteLine(GetCompactOutputDescription(sieve, passes, watch, threads, pThreads)); }
/// <summary> /// Get the compact output of the sieve run. /// </summary> private static string GetCompactOutputDescription(ISieveRunner sieve, int passes, Stopwatch watch, int threads, int pThreads) { // official syntax: // <label>;<pass_count>;<runtime>;<num_threads>;<tags (if any)> StringBuilder sb = new(); // Fields: sb.Append($"kinematics_{sieve.Name};"); sb.Append($"{passes};"); sb.AppendFormat("{0:G6};", watch.Elapsed.TotalSeconds); sb.Append($"{threads * pThreads};"); // Tags: sb.Append($"algorithm={sieve.AlgorithmType},"); sb.Append($"faithful={(sieve.IsFaithful ? "yes" : "no")},"); sb.Append($"bits={sieve.BitsPerPrime}"); sb.AppendLine(); return(sb.ToString()); }
/// <summary> /// Get the long form output of the sieve run. /// </summary> private static string GetLongOutputDescription(ISieveRunner sieve, int passes, Stopwatch watch, int threads, int pThreads) { List <string> results = new(); results.Add($"Passes: {passes}"); results.Add($"Time: {watch.Elapsed.TotalSeconds:G6} s"); results.Add($"{((double)watch.ElapsedMilliseconds / passes):F6} ms/loop"); results.Add($"Sieve Size: {sieve.SieveSize}"); results.Add($"Thread Count: {threads}"); if (sieve.IsParallel) { results.Add($"Parallel Thread Count: {pThreads}"); } results.Add($"Primes: {sieve.CountPrimes()}"); results.Add($"Valid: {PrimeData.IsCountCorrect(sieve.SieveSize, sieve.CountPrimes())?.ToString() ?? "Unable to determine"}"); if (sieve.ClearCount > 0) { results.Add($"Clear Count: {sieve.ClearCount}"); } return(results.Aggregate((a, b) => $"{a}, {b}")); }