2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 20:50 


17/04/06
256
Я написал программу умножения двух матриц и внутри использовал Parallel.For, но программы выдает ошибку:

Error 1 Cannot use ref or out parameter 'A' inside an anonymous method, lambda expression, or query expression

Ей, видимо, не нравится, что я передаю матрицу по ref для использования Parallel.For. Я конечно могу скопировать матрицу в локальную переменную, но это ведь приведет к потере производительности, теряется смысл паралельных вычислений?

Подскажите, есть ли выход?
Код:
public static double[,] MMMult (ref double[,] A, ref double[,] B)
        {
            int ANRows = A.GetLength(0);
            int ANClmns = A.GetLength(1);
            int BNRows = B.GetLength(0);
            int BNClmns = B.GetLength(1);
            double[, ] C = new double[ANRows, BNClmns];

            if (ANClmns != BNRows)
            {
                Console.WriteLine("Matrices have incompatible dimensions");
                return C; //returns zero matrix
            }
            else
            { // let's multimply two matrices

                double TempVar; //accumulates summation

                //for (int i = 0; i <= ANRows - 1; i++)
                Parallel.For(0, ANRows-1, (i) =>
                {
                    for (int j = 0; j <= BNClmns - 1; j++)
                    {
                        TempVar =0;
                        for (int k = 0; k <= ANClmns - 1; k++)
                        {
                            TempVar= TempVar+A[i,k]*B[k,j];
                        }

                        C[i, j] = TempVar;
                    }
                });
            }

           
            return C;
        }

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 21:01 
Заслуженный участник


04/05/09
4587
Я C# до конца ещё не изучил, поэтому не пинайте. ;-)

1. Зачем A и B передаются как ref? Вы ведь не меняете эти матрицы.

2. TempVar надо бы объявить внутри For(), а то параллелиться не будет.

3. Вроде не надо вычитать единицу из ANRows.

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 22:01 
Заблокирован


20/07/11

169
Bridgeport,

почитайте 23 главу из книги, которую я ранее упомянул.

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 23:30 
Заслуженный участник


09/08/09
3438
С.Петербург
venco в сообщении #473308 писал(а):
1. Зачем A и B передаются как ref? Вы ведь не меняете эти матрицы.
+1: ref нужен, только если Вы в своем методе меняете матрицы A и B, причем не поэлементно, а целиком, типа
Код:
A = new double[10, 10];

venco в сообщении #473308 писал(а):
2. TempVar надо бы объявить внутри For(), а то параллелиться не будет.
Параллелиться, скорее всего, будет, только вот работать будет неправильно (компилятор же понятия не имеет, что такое Parallel.For, функция и функция, поэтому просто использует общую копия переменной TempVar для всех потоков, без всякой синхронизацации).

venco в сообщении #473308 писал(а):
3. Вроде не надо вычитать единицу из ANRows.
+1: 3-й параметр вызова называется 'toExclusive', т. е. выполнение "цикла" закончится на последнем значении, меньшем данного.

Ну а по поводу этой ошибки
Bridgeport в сообщении #473302 писал(а):
Error 1 Cannot use ref or out parameter 'A' inside an anonymous method, lambda expression, or query expression
вот здесь почитайте внимательно: Lambda Expressions (C# Programming Guide):
Цитата:
The following rules apply to variable scope in lambda expressions:

A variable that is captured will not be garbage-collected until the delegate that references it goes out of scope.
Variables introduced within a lambda expression are not visible in the outer method.
A lambda expression cannot directly capture a ref or out parameter from an enclosing method.
A return statement in a lambda expression does not cause the enclosing method to return.
A lambda expression cannot contain a goto statement, break statement, or continue statement whose target is outside the body or in the body of a contained anonymous function.

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 23:56 


17/04/06
256
Maslov в сообщении #473339 писал(а):
venco в сообщении #473308 писал(а):
1. Зачем A и B передаются как ref? Вы ведь не меняете эти матрицы.
+1: ref нужен, только если Вы в своем методе меняете матрицы A и B, причем не поэлементно, а целиком, типа
Код:
A = new double[10, 10];


Насколько я понимаю, ref передает ссылку на обьект. Если я пропущу ref to весь массив скопируется в метод, а это потеря производительности. Или я что-то не понимаю?

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение04.08.2011, 00:11 
Заслуженный участник


09/08/09
3438
С.Петербург
Bridgeport в сообщении #473343 писал(а):
Насколько я понимаю, ref передает ссылку на обьект. Если я пропущу ref to весь массив скопируется в метод, а это потеря производительности. Или я что-то не понимаю?
Что-то не понимаете :)
Память для массивов в .Net всегда выделяется из кучи, и передаются они указателем, т. е. никакого дублирования не происходит. Поэтому меняя элементы параметра-массива, Вы работаете с исходными данными (а не с копией, созданной во время вызова метода).

Почитайте в Троелсене раздел "Типы значения и ссылочные типы" (с. 174).

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение09.08.2011, 16:20 


17/04/06
256
Всем спасибо! Заработало!
Код:
public static double[,] MMMult(double[,] A, double[,] B)
        {
            int ANRows = A.GetLength(0);
            int ANClmns = A.GetLength(1);
            int BNRows = B.GetLength(0);
            int BNClmns = B.GetLength(1);
            double[,] C = new double[ANRows, BNClmns];

            if (ANClmns != BNRows)
            {
                Console.WriteLine("Matrices have incompatible dimensions");
                return C; //returns zero matrix
            }
            else
            { // let's multimply two matrices


                Parallel.For(0, ANRows, (i) =>
                {
                    for (int j = 0; j <= BNClmns - 1; j++)
                    {

                        for (int k = 0; k <= ANClmns - 1; k++)
                        {
                            C[i, j] = C[i, j] + A[i, k] * B[k, j];
                        }

                    }
                });
            }


            return C;
        }

 Профиль  
                  
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение22.09.2011, 22:09 


17/05/11
158
venco в сообщении #473308 писал(а):
Я C# до конца ещё не изучил, поэтому не пинайте. ;-)

1. Зачем A и B передаются как ref? Вы ведь не меняете эти матрицы.

2. TempVar надо бы объявить внутри For(), а то параллелиться не будет.

3. Вроде не надо вычитать единицу из ANRows.


во-первых, С# объектно-ориентированный язык, и не стоит об этом забывать.

1. ref ~ & (c++), то есть это ссылка на объект, его копия которая висит в памяти, не меняя при этом исходного объекта. Тут преобладает безопасность скорее. То есть ваш исходный объект защищён от изменения.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group