سلامی مجدد
استاد ، من کدتون را بصورت زیر تغییر دادم ، حتی نتیجه ی معکوس هم داد :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private ListBox _listBox;
private Button _button;
private long n1;
private long n2;
private long n3;
private long MaxValue;
private const int ThreadCount = 16;
private void Form1_Load(object sender, EventArgs e)
{
_button = new Button { Parent = this, Text = "Start", Bounds = new Rectangle(ClientSize.Width - 120, 10, 100, 30) };
_listBox = new ListBox { Parent = this, Dock = DockStyle.Fill };
_button.BringToFront();
_button.Click += button_Click;
}
private void button_Click(object sender, EventArgs e)
{
_button.Enabled = false;
_listBox.Items.Add("Please wait...");
Application.DoEvents();
var stopwatch = new Stopwatch();
stopwatch.Start();
var n = 0L;
for (var i = 0L; i < 10000000000; i++)
{
//var x = DateTime.Now.Year - Environment.TickCount;
n++;
}
stopwatch.Stop();
MaxValue = ThreadCount * 20 * (int)(1000 / stopwatch.Elapsed.TotalSeconds);
stopwatch.Reset();
//n1 = 0;
//stopwatch.Start();
//SingleThreadProc();
//stopwatch.Stop();
//_listBox.Items.Add($"Single thread: {stopwatch.ElapsedMilliseconds:N0}ms Counter: {n1:N0}");
//Application.DoEvents();
//stopwatch.Reset();
n2 = 0;
stopwatch.Start();
var threads = new Thread[ThreadCount];
for (var i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(MultiThreadProc);
threads[i].Start();
}
for (var i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
stopwatch.Stop();
var e1 = stopwatch.ElapsedMilliseconds;
_listBox.Items.Add($"{ThreadCount} threads: {e1:N0}ms Counter: {n2:N0}");
Application.DoEvents();
stopwatch.Reset();
n3 = 0;
stopwatch.Start();
Parallel.For(0, ThreadCount, ActionProc);
stopwatch.Stop();
var e2 = stopwatch.ElapsedMilliseconds;
var factor = Math.Round(100.0 * (e1 - e2) / e1);
_listBox.Items.Add($"{ThreadCount} threads (Parallel): {e2:N0}ms Counter: {n3:N0} ({factor}% faster)");
_listBox.Items.Add("");
_button.Enabled = true;
}
private void SingleThreadProc()
{
var maxValue = (MaxValue / ThreadCount) * ThreadCount;
var n = 0L;
for (var i = 0L; i < maxValue; i++)
{
var x = DateTime.Now.Year - Environment.TickCount;
n++;
}
Interlocked.Add(ref n1, n);
}
private void MultiThreadProc()
{
var maxValue = MaxValue / ThreadCount;
var n = 0L;
for (var i = 0L; i < 10000000000; i++)
{
//var x = DateTime.Now.Year - Environment.TickCount;
n++;
}
Interlocked.Add(ref n2, n);
}
private void ActionProc(int num)
{
var maxValue = MaxValue / ThreadCount;
var n = 0L;
for (var i = 0L; i < 10000000000; i++)
{
//var x = DateTime.Now.Year - Environment.TickCount;
n++;
}
Interlocked.Add(ref n3, n);
}
}
}

کد زیر در حلقه ها را غیر فعال کردم :
var x = DateTime.Now.Year - Environment.TickCount;
و همچنین تعداد تکرار حلقه ها را 10000000000 بار کردم .
بعد اینکه حتی اگه بهتر هم کار کنه ، معمولا زیر 10 درصد هست . اون هم در جایی که متغییر سراسری هم در حلقه ها (درون نخ های مختلف) استفاده نمیشه که نقطه ی بحرانی پدید بیاد . بنابراین این نشون دهنده ی این نیست که این اختلاف شون بخاطر اینه که کلاس Thread از چند هسته ای (بصورت همزمان) استفاده نمیکنه اما کلاس Parallel از چند هسته بصورت همزمان استفاده نمیکنه . چون در الگوریتمی که نقطه ی بحرانی نداره (یا خیلی کم داره و در قسمت اصلی اش حدقل نقطه ی بحرانی نداره) ، استفاده از 4 هسته ی فیزیکی ، حداقل باید کارایی را 90 درصد بالاتر ببره (نسبت به تک هسته ای) اما در بهترین حالت ، کلاس Parallel فقط 10 درصد سرعت بیشتری داره که به نظر میرسه بخاطر ساختار بهتر کدهایی که مایکروسافت براش در نظر گرفت باشه . نه اینکه کلاس Parallel از چند هسته بصورت همزمان بتونه استفاده کنه و کلاس Thread نتونه استفاده کنه .
البته این باز هم نظر من هه . مستند نیست . ممکنه بخاطر معماری پردازنده ی من باشه . ممکنه هم نباشه . نمیدونم .
اگه پست 4 ام رو هم جواب میدادین ، خیلی ممنون میشدم .
خیلی ممنون که تا اینجا راهنمایی کردین .