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() ;
}
});
...全文
643 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
有时想起 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并行处理。
  • 打赏
  • 举报
回复
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 下面程序又会发生超出索引这种出错

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

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

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