for循环如何更高效 。或者其他什么方法做这个赋值运算省时间

有时想起 2017-12-01 10:37:10

代码如下:

int width = 1920;
int height = 1200;
byte[] sortnewGrey = new byte[width * height];
int sortlistCount=400;
Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
// for (int i = 0; i <100; i++)
{
lock (obj)
{
byte[] data = new byte[sortlistCount];
int num = 0;

//这部分耗时30几s 屏蔽掉的情况下耗时1s
//foreach (var item in sortlist.Values)
//{
// data[num++] = item[i];
//}
sortnewGrey[i] = data.Max() ;
}
});
...全文
588 14 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
有时想起 2017-12-04
引用 9 楼 From_TaiWan 的回复:
首先,parallel无需lock,内部已经做了处理,不会竞争sortnewGrey资源 要想只是加快速度,可以直接用for,另外,不要在循环里面执行byte[] data = new byte[sortlistCount];外边定义,里面用,如

byte[] data;
for(int I=0;i<sortnewGrey.Length;i++)
{
    data = new byte[sortlistCount];
                    int num = 0;
 
                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max() ;
}

这样,应该是较快的,lz自己用System.Diagnostics.Stopwatch测试下。
确实 直接用for 反而比parallel for更快。
  • 打赏
  • 举报
回复
有时想起 2017-12-04
引用 10 楼 sp1234 的回复:
看不懂,在内存里copy字节数组,怎么会惹上多线程呢? 当你的cpu、I/O等等有大量空闲时间时,或者你的交互界面需要轮询响应用户操作时,这可能考虑多线程并发操作。操作系统的线程调度机制需要消耗大量时间,这只会让单个任务变慢,怎么会更快呢?
你自己stopwatch看一下我代码这部分 for循环 和parallell.for循环比较下时间 看看有没有快
  • 打赏
  • 举报
回复
有时想起 2017-12-04
引用 8 楼 xuzuning 的回复:
                lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;
 
                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max() ;
                }
应写作
                    byte[] data = new byte[sortlistCount];
                    int num = 0;
 
                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                lock (obj)
                {
                    sortnewGrey[i] = data.Max() ;
                }
data 是临时变量,不会产生共享冲突。不应将费事操放在 lock 段中 没有看到 sortlist 是如何赋值的,不知道是否有必要每次循环都遍历他(显然你示例的代码是经过裁剪的) 如果有可能,应先对 sortlist 的数据源做预处理 从代码上看 sortlist.Values 是一个二维结构,可能先做一下行列转置,要好一些
sortlist 是这样赋值的:

  SortedList<double, byte[]> sortlist = new SortedList<double, byte[]>();
  Parallel.ForEach(arrFileNames, name =>
            {
                lock (obj)
                {
                    using (img = (Bitmap)Bitmap.FromFile(name))
                    {
                        double nameIndex = Convert.ToDouble(Path.GetFileNameWithoutExtension(name));
                        sortlist.Add(nameIndex, ToArray(img));
                    }
                }
            });
这是外面部分的 不在我stopwatch测试时间范围内。现在是需要每次循环都取每个图片相同位置上的像素值作为这个data数组因此 我需要每次循环都遍历它
  • 打赏
  • 举报
回复
应用软件设计主要应该是在真正的流程、大的算法上设计,例如当成千上万的事件监听触发的时候就及时地通知其它机制异步进行处理,而不是拖延到“最后时刻”去一遍遍轮询处理千百件事件。真正的效率往往出自架构设计,而不是抠个别语句。
  • 打赏
  • 举报
回复
看不懂,在内存里copy字节数组,怎么会惹上多线程呢? 当你的cpu、I/O等等有大量空闲时间时,或者你的交互界面需要轮询响应用户操作时,这可能考虑多线程并发操作。操作系统的线程调度机制需要消耗大量时间,这只会让单个任务变慢,怎么会更快呢?
  • 打赏
  • 举报
回复
秋的红果实 2017-12-02
首先,parallel无需lock,内部已经做了处理,不会竞争sortnewGrey资源 要想只是加快速度,可以直接用for,另外,不要在循环里面执行byte[] data = new byte[sortlistCount];外边定义,里面用,如

byte[] data;
for(int I=0;i<sortnewGrey.Length;i++)
{
    data = new byte[sortlistCount];
                    int num = 0;
 
                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max() ;
}

这样,应该是较快的,lz自己用System.Diagnostics.Stopwatch测试下。
  • 打赏
  • 举报
回复
有时想起 2017-12-01
引用 2 楼 hanjun0612 的回复:
我觉得是lock的问题。 既然并行执行,那么Lock又互斥了。 我测试了一下代码
static object obj = new object();
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            int width = 1920;
            int height = 1200;
            byte[] sortnewGrey = new byte[width * height];
            int sortlistCount = 400;

            //并行处理 (取消 lock)
            Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
            // for (int i = 0; i <100; i++)
            {
                //lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
                }
            });
            Console.WriteLine("Parallel nolock:"+ sw.ElapsedMilliseconds);

            sw.Restart();
            //并行处理  (开启lock)
            Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
            // for (int i = 0; i <100; i++)
            {
                lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
                }
            });
            Console.WriteLine("Parallel lock:" + sw.ElapsedMilliseconds);

            sw.Restart();
            //普通循环(取消 lock)
            for (int i = 0; i < sortnewGrey.Length; i++)
            {
                byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
            }
            Console.WriteLine("For nolock:" + sw.ElapsedMilliseconds);

            sw.Restart();
            //普通循环(开启 lock)
            for (int i = 0; i < sortnewGrey.Length; i++)
            {
                lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
                }
            }
            sw.Stop();
            Console.WriteLine("For lock:" + sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
并行使用lock,其实和普通for循环就没区别了。 那么接着你在lock中的for循环,肯定就是同步的依次排队执行Parallel中的for循环。 这就失去了Parallel的意义。
测试了 下 lock不加确实快了很多 在10s左右
  • 打赏
  • 举报
回复
正怒月神 2017-12-01
我觉得是lock的问题。
既然并行执行,那么Lock又互斥了。
我测试了一下代码
static object obj = new object();
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int width = 1920;
int height = 1200;
byte[] sortnewGrey = new byte[width * height];
int sortlistCount = 400;

//并行处理 (取消 lock)
Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
// for (int i = 0; i <100; i++)
{
//lock (obj)
{
byte[] data = new byte[sortlistCount];
int num = 0;

//这部分耗时30几s 屏蔽掉的情况下耗时1s
//foreach (var item in sortlist.Values)
//{
// data[num++] = item[i];
//}
sortnewGrey[i] = data.Max();
}
});
Console.WriteLine("Parallel nolock:"+ sw.ElapsedMilliseconds);

sw.Restart();
//并行处理 (开启lock)
Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
// for (int i = 0; i <100; i++)
{
lock (obj)
{
byte[] data = new byte[sortlistCount];
int num = 0;

//这部分耗时30几s 屏蔽掉的情况下耗时1s
//foreach (var item in sortlist.Values)
//{
// data[num++] = item[i];
//}
sortnewGrey[i] = data.Max();
}
});
Console.WriteLine("Parallel lock:" + sw.ElapsedMilliseconds);

sw.Restart();
//普通循环(取消 lock)
for (int i = 0; i < sortnewGrey.Length; i++)
{
byte[] data = new byte[sortlistCount];
int num = 0;

//这部分耗时30几s 屏蔽掉的情况下耗时1s
//foreach (var item in sortlist.Values)
//{
// data[num++] = item[i];
//}
sortnewGrey[i] = data.Max();
}
Console.WriteLine("For nolock:" + sw.ElapsedMilliseconds);

sw.Restart();
//普通循环(开启 lock)
for (int i = 0; i < sortnewGrey.Length; i++)
{
lock (obj)
{
byte[] data = new byte[sortlistCount];
int num = 0;

//这部分耗时30几s 屏蔽掉的情况下耗时1s
//foreach (var item in sortlist.Values)
//{
// data[num++] = item[i];
//}
sortnewGrey[i] = data.Max();
}
}
sw.Stop();
Console.WriteLine("For lock:" + sw.ElapsedMilliseconds);
Console.ReadLine();
}

并行使用lock,其实和普通for循环就没区别了。
那么接着你在lock中的for循环,肯定就是同步的依次排队执行Parallel中的for循环。
这就失去了Parallel的意义。
  • 打赏
  • 举报
回复
事理 2017-12-01
把这个拆分成两个for循环遍历,譬如sortlist.Values是100个数量,第一个for循环1-50,另一个循环51-100 第一个for循环放到一个a1方法里面,用全局变量a标记任务完成,第二个for循环放到a2方法里面,用全局变量b标记任务完成,然后用2个线程,调用a1()和a2(), Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) => // for (int i = 0; i <100; i++) { lock (obj) { byte[] data = new byte[sortlistCount]; int num = 0; Thread threadA = new Thread(new ParameterizedThreadStart(a1)); threadA.IsBackground = true; threadA.Start(data); Thread threadB = new Thread(new ParameterizedThreadStart(a2)); threadB.IsBackground = true; threadB.Start(data); while(true){ if(全局变量1==true && 全局变量2==true){break;} Thread.Sleep(100); } sortnewGrey[i] = data.Max() ; } }); 这样应该能节省一半时间,如果再拆分,时间就会更少了,不一定是最好的办法,可以参考下
  • 打赏
  • 举报
回复
xuzuning 2017-12-01
                lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;
 
                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max() ;
                }
应写作
                    byte[] data = new byte[sortlistCount];
                    int num = 0;
 
                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                lock (obj)
                {
                    sortnewGrey[i] = data.Max() ;
                }
data 是临时变量,不会产生共享冲突。不应将费事操放在 lock 段中 没有看到 sortlist 是如何赋值的,不知道是否有必要每次循环都遍历他(显然你示例的代码是经过裁剪的) 如果有可能,应先对 sortlist 的数据源做预处理 从代码上看 sortlist.Values 是一个二维结构,可能先做一下行列转置,要好一些
  • 打赏
  • 举报
回复
姜团长 2017-12-01

int width = 1920;
int height = 1200;
byte[] sortnewGrey = new byte[width * height];
int sortlistCount=400;

byte[] data = new byte[sortlistCount];
int num = 0;
Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
// for (int i = 0; i <100; i++)
{
	lock (obj)
	{
		num = 0;

		//这部分耗时30几s      屏蔽掉的情况下耗时1s
		foreach (var item in sortlist.Values)
		{
		    data[num] = item[i];
			MaxNum = data[num] > MaxNum ? data[num]:MaxNum;
			num++;
		}
		sortnewGrey[i] = MaxNum ;
	}
});
  • 打赏
  • 举报
回复
正怒月神 2017-12-01
引用 4 楼 u011672494 的回复:
但是不加lock 下面程序又会发生超出索引这种出错
这可能还是要看看你之后的代码了,因为就这段代码来说,并没有达到你期望的Parallel并行处理。
  • 打赏
  • 举报
回复
exception92 2017-12-01
lock的使用会降低性能的,它目的是为了在使用多线程的时候能达到线程同步,parallel并行其实也是多线程执行,不加锁的话 它的操作会有可能损坏数据的!其实for循环是非常快的,慢的应该是 new了几百万个 byte数组 然后 data.Max()。
  • 打赏
  • 举报
回复
有时想起 2017-12-01
引用 2 楼 hanjun0612 的回复:
我觉得是lock的问题。 既然并行执行,那么Lock又互斥了。 我测试了一下代码
static object obj = new object();
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            int width = 1920;
            int height = 1200;
            byte[] sortnewGrey = new byte[width * height];
            int sortlistCount = 400;

            //并行处理 (取消 lock)
            Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
            // for (int i = 0; i <100; i++)
            {
                //lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
                }
            });
            Console.WriteLine("Parallel nolock:"+ sw.ElapsedMilliseconds);

            sw.Restart();
            //并行处理  (开启lock)
            Parallel.For(0, sortnewGrey.Length, (i) => //sortnewGrey.Length, (i) =>
            // for (int i = 0; i <100; i++)
            {
                lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
                }
            });
            Console.WriteLine("Parallel lock:" + sw.ElapsedMilliseconds);

            sw.Restart();
            //普通循环(取消 lock)
            for (int i = 0; i < sortnewGrey.Length; i++)
            {
                byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
            }
            Console.WriteLine("For nolock:" + sw.ElapsedMilliseconds);

            sw.Restart();
            //普通循环(开启 lock)
            for (int i = 0; i < sortnewGrey.Length; i++)
            {
                lock (obj)
                {
                    byte[] data = new byte[sortlistCount];
                    int num = 0;

                    //这部分耗时30几s      屏蔽掉的情况下耗时1s
                    //foreach (var item in sortlist.Values)
                    //{
                    //    data[num++] = item[i];
                    //}
                    sortnewGrey[i] = data.Max();
                }
            }
            sw.Stop();
            Console.WriteLine("For lock:" + sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
并行使用lock,其实和普通for循环就没区别了。 那么接着你在lock中的for循环,肯定就是同步的依次排队执行Parallel中的for循环。 这就失去了Parallel的意义。
但是不加lock 下面程序又会发生超出索引这种出错
  • 打赏
  • 举报
回复
相关推荐
课程设计-基于C++的mfc框架的学生社团管理系统(源码+数据库+报告).zip 本系统实现的功能 本程序为单文档应用程序,主程序界面能实现查询社团信息、修改社团信息、删除社团信息、添加社团信息、入团、退团、用户登录、和用户管理功能其中修改社团信息、删除社团信息、添加社团信息和用户管理需要用户登录后才能使用,未登录就点击使用的会会弹出对话框显示您还没有登录,点击登录按钮会弹出用户登录对话框输入正确的用户名称和密码若验证成功则会显示登录成功并显示出您用有的权限高级管理员或者是普通管理员,高级管理员则可以对社团信息进行修改、删除、添加。点击入团按钮会弹出加入社团对话框,在对话框内填上相应的信息后点击确定成功加入后会有相关提示,若没有成功则有可能您输入的社团不存在,点击退团按钮弹出退出社团对话框,输入您要退出的社团名称和学号点击确定如果成功退出会显示成功的标志,否则的话就是您没有假如该社团活着您填的信息不完全。在主程序对话框中可以直接在控件内输入要修改的社团信息,然后点击修改按钮,分别输入控件中的内容然后点击添加按钮,若要添加的社团当前没有的话则添加成功,否则会失败。登录了以后点击用户管理按钮则会弹出用户管理对话框,在该对话框内可以修改用户密码,高级管理员还能注册新用户。
发帖
C#
加入

10.7w+

社区成员

.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
申请成为版主
帖子事件
创建了帖子
2017-12-01 10:37
社区公告

让您成为最强悍的C#开发者