2014 dxdy logo

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

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




 
 Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 20:50 
Я написал программу умножения двух матриц и внутри использовал 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 
Я C# до конца ещё не изучил, поэтому не пинайте. ;-)

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

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

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

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

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

 
 
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение03.08.2011, 23:30 
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 
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 
Bridgeport в сообщении #473343 писал(а):
Насколько я понимаю, ref передает ссылку на обьект. Если я пропущу ref to весь массив скопируется в метод, а это потеря производительности. Или я что-то не понимаю?
Что-то не понимаете :)
Память для массивов в .Net всегда выделяется из кучи, и передаются они указателем, т. е. никакого дублирования не происходит. Поэтому меняя элементы параметра-массива, Вы работаете с исходными данными (а не с копией, созданной во время вызова метода).

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

 
 
 
 Re: Паралельные вычисления и передача параметра по ref C#
Сообщение09.08.2011, 16:20 
Всем спасибо! Заработало!
Код:
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 
venco в сообщении #473308 писал(а):
Я C# до конца ещё не изучил, поэтому не пинайте. ;-)

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

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

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


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

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

 
 
 [ Сообщений: 8 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group