Member 10052408 Ответов: 4

C# - как запускать несколько задач на определенных нескольких ядрах/процессорах одновременно/синхронно


Всем Привет,

У меня есть несколько задач, и мне нужно запустить их на определенных нескольких ядрах или процессорах

одновременно. Например, если у меня есть две разные задачи или только одна задача, но я выполню ее дважды

я хочу запустить эти две задачи на определенных ядрах или процессорах одновременно, как будет работать task1

на processor1 и task2 будут выполняться на processor2 одновременно. я знаю, как запустить каждый конкретный

процессор, но я не знаю, как запустить их одновременно. Я пытался использовать многопоточность

затем параллельная библиотека задач для одновременного выполнения различных задач на определенных процессорах но я

провалившийся. в приведенном ниже коде я пытался использовать многопоточность, но она не работает или я могу использовать задачу

параллельная библиотека???

ПОЖАЛУЙСТА, ПОМОГИТЕ!!!!!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace ConsoleApplication14
{
    class Program
    {
        
        public static double DumbCountSqr(int dumnum)
        {

            Random random = new Random();
            int randomNumber = random.Next(0, 10);
            double result = 0;
            for (int i = 1; i < 10000; i++)
            {
                for (int j = 1; j < 10000; j++)
                {
                    result += random.Next(0, 10) * Math.Sqrt(i) * Math.Sqrt(j) + Math.Abs(Math.Sqrt(i));
                }
            }
            return result;
        }

        public static void Main()
        {

            Thread t = new Thread(new ThreadStart(Go));
            t.Start();


            for (int i = 0; i < 1; i++)
            {

                Process Proc = Process.GetCurrentProcess();
                long AffinityMask = (long)Proc.ProcessorAffinity;

                AffinityMask = 0x0004;//processor    3
                Proc.ProcessorAffinity = (IntPtr)AffinityMask;

                var result1 = DumbCountSqr(i);
                Console.WriteLine("result1 =  " + result1);

            }
        }
        
        
       public static void Go()
        {

            for (int i = 0; i < 1; i++)
            {
                
                    Process Proc = Process.GetCurrentProcess();
                    long AffinityMask = (long)Proc.ProcessorAffinity;

                    AffinityMask = 0x0001;//processor    1
                    Proc.ProcessorAffinity = (IntPtr)AffinityMask;

                    var result2 = DumbCountSqr(i);
                    Console.WriteLine("result2 =  " + result2);
   
            }
   
        }

    }
}

4 Ответов

Рейтинг:
30

Sergey Alexandrovich Kryukov

Позвольте мне дать вам очень короткое представление.

You can use threads in a way abstracted from the CPU cores. And the OS associates cores with threads using its own. In almost all cases, this is the very best option. I would not recommend touching process and thread affinity at all. The cases when you may find it beneficial to touch affinity are very rare, and I would call all of them "really bad cases". For example, if you have some really bad piece of hardware which requires extensive periodic polling (really good devices work by interrupts), you may decided to sacrifice one core to this problem in order to make behavior processes/thread using other cores more predictable, especially of some are more or less mission-critical (I won't risk saying "real-time" which would be a very different and more advanced topic, hardly about Windows). Or, just the opposite, you may have just one very mission-critical application, to dedicate a core to it; but this is hard to do, because other application may interfere, as they "don't know" about your decision.

Если вы хотите рассмотреть TPL (Parallel), вы бы двигались прямо противоположным образом: не только задачи абстрагируются от ядер, но и от потоков. На самом деле TPL основан на потоках, но разработчик, в общем случае, не знает, какой фрагмент кода выполняется в каком потоке, какие фрагменты выполняются параллельно, а какие находятся в одном потоке. TPL автоматически отправляет код между потоками.

В общем, это все. Если у вас есть какие-то конкретные цели (действительно особые и конкретные), вы можете получить шанс получить некоторые практические советы, Если вы ими поделитесь.

—СА


Рейтинг:
1

Member 10052408

Я попробовал оба метода , threadapproach и taskapproach, но не смог заставить две или более задач начать работать одновременно, потому что, когда я проверяю загрузку процессора, я вижу, что только один из конкретных процессоров работает со 100%, но я хочу, чтобы два или более конкретных процессора работали со 100% или почти 100% одновременно.

Если я суммирую то, что я пытаюсь сделать, то я хочу делать параллельные вычисления, но я хочу указать, какие процессоры должны работать параллельно.

Вот ваш код, я сделал некоторые изменения, но он не делает то, что я хочу.

Во-первых, у меня есть математическая функция, случайное вычисление, затем я хотел бы, чтобы процессор 2 и 3 работали над этой задачей одновременно, чтобы получить результат.
Когда я запускаю код, только один из конкретных процессоров работает со 100%, а не оба одновременно.

<pre>using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ConsoleApplication
{
    class Program
    {
        public static double DumbCountSqr(int dumnum)
        {
            // My sample task - just a mathematical calculation

            Random random = new Random();
            int randomNumber = random.Next(0, 10);
            double result = 0;
            for (int i = 1; i < 20000; i++)
            {
                for (int j = 1; j < 15000; j++)
                {
                    result += random.Next(0, 10) * Math.Sqrt(i) * Math.Sqrt(j) + Math.Abs(Math.Sqrt(i));
                }
            }
            return result;
        }

        public static void MyTask()
        {
            for (int i = 0; i < 1; i++)
            {
                // the task,mathematical calculation, should run only on processor 3

                Process Proc = Process.GetCurrentProcess();
                long AffinityMask = (long)Proc.ProcessorAffinity;

                AffinityMask = 0x0004;//processor    3
                Proc.ProcessorAffinity = (IntPtr)AffinityMask;

                var result1 = DumbCountSqr(i);
                Console.WriteLine("result1 =  " + result1);

            } 
        }
        

        public static void MyTask2()
        {
            for (int i = 1; i < 2; i++)
            {
                // the task,mathematical calculation, should run only on processor 2

                Process Proc = Process.GetCurrentProcess();
                long AffinityMask = (long)Proc.ProcessorAffinity;

                AffinityMask = 0x0002;//processor    2
                Proc.ProcessorAffinity = (IntPtr)AffinityMask;

                var result2 = DumbCountSqr(i);
                Console.WriteLine("result2 =  " + result2);

            }
        }


       
        static void ThreadApproach()
        {
            var t1 = new Thread(MyTask);
            var t2 = new Thread(MyTask2);

            // Bound your threads to a specific processor if you want and so on.
            // I do not know how to bound threads to a specific processor???????


            // processor 2 and 3 should start to work on the task simultaneously 
            // with the way i bound tasks to processors but they do not start simultaneously???????
            t1.Start();
            t2.Start();

            // The tasks should start running simultaneously at this point.
            // Tasks do not start running simultaneously because when i check cpu utilization
            // only one processor is working with 100%

            // Optional if you want to synchronously wait for completion.
            t1.Join();
            t2.Join();
        }
        

        /*
        static void TaskApproach()
        {
            var t1 = Task.Factory.StartNew(() => MyTask());
            var t2 = Task.Factory.StartNew(() => MyTask2());

           
            

            // Optional if you want to synchronously wait for completion.
            // However I recomend you async/await if you are going to work with Tasks.
            // But this is another topic.
            Task.WaitAll(t1, t2);
        }
        */
        static void Main(string[] args)
        {
            // Use one of these:
            ThreadApproach();
            // Or
            // TaskApproach();

            Console.WriteLine("Job Completed!");
            Console.ReadLine();
        }
    }
}


gggustafson

Еще раз, прочитай ответ Сергея. Не пытайтесь делать то, что вы пытаетесь сделать. Я запускал приложения с 37 потоками. Всякий раз, когда я пытался играть с аффинити, я всегда снижал общую производительность. Аффинити-это то, что Коттер очень хорошо разработал. Я не думаю, что вы можете превзойти его работу.

Для чего нужны циклы for в каждой задаче? они оба выполняются только один раз - нет необходимости в цикле.

Рабочая функция может отличаться по времени выполнения для каждого вызова. Удалите случайность, чтобы иметь возможность делать выводы о времени выполнения потока.

Настоятельно рекомендую вам прочитать Параллельные вычисления и близость процессоров. Никогда не стоит недооценивать планировщик Windows Vista это относится ко всем ОС, а не только к Vista.

Рейтинг:
0

Yandy Zaldivar

Привет, я собираюсь дать вам два решения, и вы выбираете одно или другое в зависимости от ваших потребностей. Я использовал в качестве руководства не демонстрацию вашего кода, а текст вашего вопроса.

- Выберите ThreadApproach, если вы хотите иметь явный контроль над потоком, который будет выполнять вашу задачу, включая процессор, на котором она будет работать, размер стека и так далее.

- Выберите TaskApproach, если вы заботитесь только о том, чтобы делать работу быстро и параллельно, позволяя среде выполнения делать это за вас.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication
{
   class Program
   {
      static void MyTask() { /*Implement your long running task here*/ }

      static void ThreadApproach()
      {
         var t1 = new Thread(MyTask);
         var t2 = new Thread(MyTask);

         // Bound your threads to a specific processor if you want and so on.

         t1.Start();
         t2.Start();

         // The tasks should start running simultaneously at this point.

         // Optional if you want to synchronously wait for completion.
         t1.Join();
         t2.Join();
      }

      static void TaskApproach()
      {
         var t1 = Task.Run(() => MyTask());
         var t2 = Task.Run(() => MyTask());

         // Optional if you want to synchronously wait for completion.
         // However I recomend you async/await if you are going to work with Tasks.
         // But this is another topic.
         Task.WaitAll(t1, t2);
      }

      static void Main(string[] args)
      {
         // Use one of these:
         ThreadApproach();
         // Or
         TaskApproach();

         Console.WriteLine("Job Completed!");
         Console.ReadLine();
      }
   }
}


Рейтинг:
0

Yandy Zaldivar

Привет, проблема в вашем дизайне заключается в том, что вы используете маску сходства на уровне процессора. Если вы установите if в 2, то все ваши потоки будут работать на процессоре 2, а если вы установите его в 3, то все ваши потоки будут работать на процессоре 3.

Если вы хотите, чтобы поток 1 выполнялся на процессоре 2, а поток 2 - на процессоре 3, используйте следующий код:

Process.GetCurrentProcess().Threads[1].ProcessorAffinity = (IntPtr)2;
Process.GetCurrentProcess().Threads[2].ProcessorAffinity = (IntPtr)3;


Помните, что потоки[0] - это ваш основной поток, а потоки[1] и [2] - это ваши вновь созданные потоки. Для получения дополнительной справки, пожалуйста, прочтите MSDN по этой теме: ProcessThread.Свойства Processoraffinity

Йенди