怎样提高多线程的运行效率。

花开花折 2020-02-27 02:41:59
问题描述:
硬件配置 intel core(TM)-i7-7700 CPU C#
原帖在这,重新开一个。 https://bbs.csdn.net/topics/395944192
1:单独执行方法FindShapeModel()假设用时100ms;我有4个类似的方法开多线程同时运行,理论上应该也是100ms左右,但实测发现需要400ms左右。也就是说多线程完成没启到作用。
2:4个FindShapeModel()方法完成没有互锁什么,都是独立的。
3:也有设置线程让线程运行在单独一个CPU上,通过StopWatch监控发现也是交替在运行中,
4:现求解让4个线程同时运行的方法。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CPUParallel
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}


long frequency = 0;//计时用的时钟频率
short[] isFinish = new short[10];
long[] time = new long[50];

private Stopwatch watch = new Stopwatch();
private Thread[] MyThread = new Thread[4];


[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool QueryPerformanceFrequency(ref long performanceFrequency);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool QueryPerformanceCounter(ref long performanceCount);

[DllImport("kernel32.dll")]
public static extern uint GetLastError();


//获取系统运行时间毫秒级别
[DllImport("kernel32.dll")]
static extern uint GetTickCount();


//SetThreadAffinityMask 指定hThread 运行在 核心 dwThreadAffinityMask
[DllImport("kernel32.dll")]
static extern UIntPtr SetThreadAffinityMask(IntPtr hThread, UIntPtr dwThreadAffinityMask);

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetCurrentProcess();

[DllImport("kernel32.dll", SetLastError = true)]
public static extern int GetCurrentProcessorNumber();


//得到当前线程的handler
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThread();

[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();

private void CheckMyThreadIsFinish(object obj)
{
bool loop = true;
while (loop)
{
Thread.Sleep(0);
if ((isFinish[0] == 1) && (isFinish[1] == 1))
{
QueryPerformanceCounter(ref time[10]);
double totalTime = Math.Round(1000.0 * (time[10] - time[15]) / frequency, 1);
Trace.WriteLine("最终检测完成时间:" + totalTime + " 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"));

isFinish[0] = 0;
isFinish[1] = 0;
}
}
}

private short FindShapeModel()
{
//截取当前窗体图像
int Width = 1088;
int Height = 686;

int ClientSizeWidth = 1072;
int ClientSizeHeight = 647;

for (int i = 0; i < 40; i++)
{
Bitmap bitFormImg = new Bitmap(Width, Height);

//this.DrawToBitmap(bitFormImg, new Rectangle(0, 0, Width, Height));
int border = (Width - ClientSizeWidth) / 2;//边框宽度
int caption = (Height - ClientSizeHeight) - border;//标题栏高度

//截取签字区域图像(去边框、标题栏)
Bitmap bitSignatureImg = bitFormImg.Clone(new Rectangle(border, caption, ClientSize.Width, ClientSize.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//创建内存流
MemoryStream Ms = new MemoryStream();
//将图像保存至内存流
bitSignatureImg.Save(Ms, ImageFormat.Bmp);
bitFormImg.Dispose();
bitSignatureImg.Dispose();

byte[] img = new byte[Ms.Length];
Ms.Position = 0;
Ms.Read(img, 0, Convert.ToInt32(Ms.Length));
Ms.Close();
string result = Convert.ToBase64String(img);

int COUNT = GetCurrentProcessorNumber();
//Trace.WriteLine("ID "+i+" FindShapeModel0:" + "CPUID: " + COUNT + " 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"));
Trace.WriteLine("ID " + i + " FindShapeModel0:" + "CPUID: " + COUNT + " 时间:" + Math.Round(watch.Elapsed.TotalMilliseconds, 3));

}

return 1;

}


private short FindShapeModel1()
{
//截取当前窗体图像
int Width = 1088;
int Height = 686;

int ClientSizeWidth = 1072;
int ClientSizeHeight = 647;


for (int i = 0; i < 40; i++)
{
Bitmap bitFormImg = new Bitmap(Width, Height);

//this.DrawToBitmap(bitFormImg, new Rectangle(0, 0, Width, Height));
int border = (Width - ClientSizeWidth) / 2;//边框宽度
int caption = (Height - ClientSizeHeight) - border;//标题栏高度

//截取签字区域图像(去边框、标题栏)
Bitmap bitSignatureImg = bitFormImg.Clone(new Rectangle(border, caption, ClientSize.Width, ClientSize.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//创建内存流
MemoryStream Ms = new MemoryStream();
//将图像保存至内存流
bitSignatureImg.Save(Ms, ImageFormat.Bmp);
bitFormImg.Dispose();
bitSignatureImg.Dispose();

byte[] img = new byte[Ms.Length];
Ms.Position = 0;
Ms.Read(img, 0, Convert.ToInt32(Ms.Length));
Ms.Close();
string result = Convert.ToBase64String(img);

int COUNT = GetCurrentProcessorNumber();
//Trace.WriteLine("ID "+i+" FindShapeModel0:" + "CPUID: " + COUNT + " 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"));
Trace.WriteLine("ID " + i + " FindShapeModel1:" + "CPUID: " + COUNT + " 时间:" + Math.Round(watch.Elapsed.TotalMilliseconds, 3));

}

return 1;

}



private void FindShapeModel(object obj)
{
Thread.BeginThreadAffinity();
IntPtr handle = GetCurrentThread();


UIntPtr rtn = SetThreadAffinityMask(handle, new UIntPtr(0x0001));
uint rtn1 = GetLastError();
isFinish[0] = FindShapeModel();

Thread.EndThreadAffinity();

}

private void FindShapeModel1(object obj)
{
Thread.BeginThreadAffinity();
IntPtr handle = GetCurrentThread();

UIntPtr rtn = SetThreadAffinityMask(handle, new UIntPtr(64));
uint rtn1 = GetLastError();
isFinish[1] = FindShapeModel1();

Thread.EndThreadAffinity();

}

private void FindShapeModel2(object obj)
{
QueryPerformanceCounter(ref time[25]);
Thread.BeginThreadAffinity();
IntPtr handle = GetCurrentThread();

UIntPtr rtn = SetThreadAffinityMask(handle, new UIntPtr(64));
uint rtn1 = GetLastError();
isFinish[1] = FindShapeModel();
Thread.EndThreadAffinity();

QueryPerformanceCounter(ref time[26]);
double totalTime = Math.Round(1000.0 * (time[26] - time[25]) / frequency, 1);
Trace.WriteLine("直接调用FindShapeModel()方法:" + totalTime + " 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"));
}



private void Form1_Load(object sender, EventArgs e)
{
QueryPerformanceFrequency(ref frequency);

Thread thread = new Thread(CheckMyThreadIsFinish);
int id = thread.ManagedThreadId;
thread.Start();
}

private void button1_Click(object sender, EventArgs e)
{
object obj = null;
watch.Restart();
QueryPerformanceCounter(ref time[15]);
isFinish[0] = 0;
isFinish[1] = 0;

MyThread[0] = new Thread(new ParameterizedThreadStart(FindShapeModel));
MyThread[0].Start(obj);

MyThread[1] = new Thread(new ParameterizedThreadStart(FindShapeModel1));
MyThread[1].Start(obj);
}

private void button2_Click(object sender, EventArgs e)
{
watch.Restart();
QueryPerformanceCounter(ref time[25]);
MyThread[0] = new Thread(new ParameterizedThreadStart(FindShapeModel2));
MyThread[0].Start(null);

}
}
}




...全文
642 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
jamsunyue 2020-03-05
  • 打赏
  • 举报
回复
怎么说呢,分那么高,又没法说清楚. 楼主要不先思考一下 thread.Start() 后怎么给 About(), 另外 委托 在那里. 对程序而言有开必有关, 不然内存早晚溢出, CPU再好也用不上.
Cryking 2020-03-03
  • 打赏
  • 举报
回复
线程的切换和创建都是有开销的 https://blog.csdn.net/edcvf3/article/details/83796091?utm_source=app
threenewbee 2020-02-27
  • 打赏
  • 举报
回复
这种低端cpu没有什么并行的价值。在Xeon E5 E7上测试吧。
正怒月神 2020-02-27
  • 打赏
  • 举报
回复
你试试看把clone文件的操作,放到循环外, 循环内单独操作memorystream
github_36000833 2020-02-27
  • 打赏
  • 举报
回复
引用:Detect and Avoid Memory Bottlenecks
... 数据在内存模块和CPU之间,通过总线进行移动。大量的内存操作,就像在大型集会后试图离开停车场的汽车一样,它们彼此争吵,争夺相同的空间并彼此减速。 ...
原文见: https://software.intel.com/en-us/articles/detect-and-avoid-memory-bottlenecks i7-7700的 一级数据缓存为:4 * 32KB 二级缓存为:4 * 256KB 三级缓存为:8 MB 而你示例中的每个循环:
Bitmap bitFormImg = new Bitmap(Width, Height);
// 大概要2.7兆内存。

Bitmap bitSignatureImg = bitFormImg.Clone(new Rectangle(border, caption, ClientSize.Width, ClientSize.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// 大概要2.7兆内存。

MemoryStream Ms = new MemoryStream();
bitSignatureImg.Save(Ms, ImageFormat.Bmp);
// 大概要2.7兆内存。

byte[] img = new byte[Ms.Length];
Ms.Read(img, 0, Convert.ToInt32(Ms.Length));
// 大概要2.7兆内存。

string result = Convert.ToBase64String(img);
// 大概要8兆内存。
花开花折 2020-02-27
  • 打赏
  • 举报
回复
引用 1 楼 github_36000833 的回复:
你例子里的任务,存在大量的内存IO,和大量的垃圾回收,并行的效果不会很好。


A:那个For 循环主要是为了增加模拟测试时间,实际代码没有这么大量的内存IO,但内存IO肯定是会有的。
B:你的意思是如果内存IO比较小的,可以用并行Parallel
github_36000833 2020-02-27
  • 打赏
  • 举报
回复
你例子里的任务,存在大量的内存IO,和大量的垃圾回收,并行的效果不会很好。

17,748

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧