тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 07:23
Оценка: :)
После того, как мне здесь объяснили, что я ничего не понимаю , ушел я с горя в "Философию" и ответил там на одно сообщение, прямого отношения к тематике этого форума не имеющее. Однако черт меня угораздил там мимоходом упомянуть C#, в результате чего Sinclair нашел меня и там (http://www.rsdn.ru/Forum/Message.aspx?mid=1404835&only=1
Автор: Sinclair
Дата: 27.09.05
) и продолжил объяснять мне, что я ничего не понимаю. И состоялась у нас вот такая дискуссия

PD>>К примеру (банальный) решиться мне, скажем, на C# матричные операции производить или же С++ DLL для этого написать, а в Шарпе только вызывать ее.

S>Ты не пробовал, к примеру, вот здесь читать?

PD>Прочитал, спасибо. Увы, этого мне недостаточно. Во-первых, хотелось бы еще знать, сколько памяти они при этом потребили. Во-вторых, здесь используется совсем небольшие объемы данных, а вот что будет при обработке массивов размером в Мбайты ? Насколько эффективен доступ к массивам ? Тебе не хуже меня известно, что даже в чистом С++ при неудачном размере строки масиива (например, 4097 байт) можно сильно проиграть. И т.д. И т.д


Написал я все это, а потом подумал — а чего я, собственно, голословными утверждениями занимаюсь. Сложно, что ли мне это самое умножение матрици самому сделать и посмотреть время. Ну и сделал, и посмотрел.

Вот текст на С++

        float ** a, **b, **c;
    int i,j,k,nSize = 1000;
    float temp;

    int nTimeStart = GetTickCount();
    a = new float*[nSize];
    for( i = 0; i < nSize; i++)
        a[i] = new float[nSize];
    for(i = 0; i < nSize; i++)
        for(j = 0; j < nSize; j++)
            a[i][j] = 1;

    b = new float*[nSize];
    for( i = 0; i < nSize; i++)
        b[i] = new float[nSize];
    for(i = 0; i < nSize; i++)
        for(j = 0; j < nSize; j++)
            b[i][j] = 1;
    
    c = new float*[nSize];
    for( i = 0; i < nSize; i++)
        c[i] = new float[nSize];
    
    for(i = 0; i < nSize; i++)
    {
        for(j = 0; j < nSize; j++)
        {
            temp = 0;
            for( k = 0; k < nSize; k++)
                temp += a[i][k] * b[k][j];
            c[i][j] = temp;
        }
    }

    int nTimeEnd = GetTickCount();
    printf("Time = %d\n", (nTimeEnd - nTimeStart) /1000);


Время работы этой программы на моем Pentium IV 1600 MHz 768 Mb — 33 секунды.

Теперь то же на С#


        float[][] a, b, c;
    int i,j,k,nSize = 10;
    float temp;

    DateTime nTimeStart = DateTime.Now;
    a = new float[nSize][];
    for( i = 0; i < nSize; i++)
        a[i] = new float[nSize];
    for(i = 0; i < nSize; i++)
        for(j = 0; j < nSize; j++)
            a[i][j] = 1;

    b = new float[nSize][];
    for( i = 0; i < nSize; i++)
        b[i] = new float[nSize];
    for(i = 0; i < nSize; i++)
        for(j = 0; j < nSize; j++)
            b[i][j] = 1;
    
    c = new float[nSize][];
    for( i = 0; i < nSize; i++)
        c[i] = new float[nSize];
    
            for(i = 0; i < nSize; i++)
            {
                for(j = 0; j < nSize; j++)
                {
                    temp = 0;
                    for( k = 0; k < nSize; k++)
                        temp += a[i][k] * b[k][j];
                    c[i][j] = temp;
                }
            }
        DateTime nTimeEnd = DateTime.Now;

    Console.WriteLine("Time = {0}", (nTimeEnd - nTimeStart));


Время работы — 4 минуты 6 секунд.

Подумал я и решил попробовать вторую матрицу (b) по столбцам расположить. Поскольку матрицы квадратные, а все элементы равны 1 то достаточно просто сделать вид, что это так, т.е. заменить

temp += a[i][k] * b[k][j];

на

temp += a[i][k] * b[j][к];

Результат — 18 секунд как на С++, так и на С#.

Еще один эксперимент на С# сделал — заменил кусочный массив на цельный, т.е.


            float[,] a, b, c;
            int i,j,k,nSize = 1000;
            float temp;

            DateTime nTimeStart = DateTime.Now;
            a = new float[nSize,nSize];
            for(i = 0; i < nSize; i++)
                for(j = 0; j < nSize; j++)
                    a[i,j] = 1;

            b = new float[nSize, nSize];
            for(i = 0; i < nSize; i++)
                for(j = 0; j < nSize; j++)
                    b[i,j] = 1;
    
            c = new float[nSize,nSize];
    
            for(i = 0; i < nSize; i++)
            {
                for(j = 0; j < nSize; j++)
                {
                    temp = 0;
                    for( k = 0; k < nSize; k++)
                        temp += a[i,k] * b[k,j];
                    c[i,j] = temp;
                }
            }



Результат — 56 секунд. На С++ делать этот тест не стал — лень. .

Итак, имеем

а) матрица а по строкам, матрица b по столбцам — быстродействие C# не хуже С++
б) матрицы целым куском — на С# имеем 3-кратное замедление по сравнению с a)
в) матрица а по строкам, матрица b по строкам — С++ в 2 раза хуже, чем С++ для a), что вполне естественно (ИМХО в основном за счет перегрузки кэша процессора), но C# дает 7-кратный проигрыш по сравнению с С++ и 14-кратный по сравнению с a). Причина понятна — имеем массивы массивов, и на каждом проходе внутреннего цикла идет обращение к другому массиву (другой строке) матрицы b, что, по-видимому, и вызывает этот эффект.

Мой вопрос — если все-таки матрица b должна храниться в формате a),(просьба не обсуждать, зачем это нужно и не советовать выбрать иной формат) можно что-то сделать ? Я не против fixed, но не пойму, как его здесь применить. Рихтер утверждает, что fixed можно применить только к массивам из простых типов, а здесь все же массив массивов.
With best regards
Pavel Dvorkin
Re: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 07:26
Оценка:
Забыл сказать. Под C++ везде имеется в виду unmanaged приложение.
With best regards
Pavel Dvorkin
Re: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 08:00
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

Вообще то ты можешь содать свой хип для валуе типов содержащие только валуе типы.
Пользуясь тем, что массывы более 80 кб не поддвергаются дефрагментации. И можешь на полную катушку использовать унсейв.
Посмотри
http://rsdn.ru/Forum/Message.aspx?mid=701354&amp;only=1
Автор: Serginio1
Дата: 30.06.04
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[2]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 08:11
Оценка:
Здравствуйте, Serginio1, Вы писали:

P.S.

При чем создание хиппа под структуры определенного размера вещь тривиальная и активно используется в том же в нативе, для более выстрого выделения памяти и освобождения.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re: тест с матрицами
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.09.05 08:23
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

Вопрос: в каких режимах компилял? Что за компилятор использовался для С++?
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: тест с матрицами
От: GlebZ Россия  
Дата: 29.09.05 08:31
Оценка: 1 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

Это не первый флейм по этому поводу.
здесь
Автор: McSeem2
Дата: 14.01.05

Или вообще по поиску
здесь

С уважением, Gleb.
Re[2]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 08:41
Оценка:
Здравствуйте, GlebZ, Вы писали:

По поводу [,] в новых бэттах не поправили ????

А насчет джагеттов то там скорее всего происходит проверка за границы. Опять как в новых версиях ????
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[2]: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 08:53
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Pavel Dvorkin, Вы писали:


S>Вопрос: в каких режимах компилял? Что за компилятор использовался для С++?


Компиляторы в обоих случаях из Visual Studio 7.1.3088.
Net Framework 1.1.4322 SP1

Насчет режимов — сорри, виноват, там был Debug. Каюсь и посыпаю голову пеплом

Привожу данные для Release

С++, матрица b по столбцам — 5 сек.
С++, матрица b по строкам — 17 сек.
C#, матрица b по столбцам — 7 сек.
C#, матрица b по строкам — 4 минуты 5 сек.
C#, матрицы двумерные — 36 секунд.
With best regards
Pavel Dvorkin
Re[2]: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 08:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Pavel Dvorkin, Вы писали:


S> Вообще то ты можешь содать свой хип для валуе типов содержащие только валуе типы.

S> Пользуясь тем, что массывы более 80 кб не поддвергаются дефрагментации. И можешь на полную катушку использовать унсейв.
S> Посмотри
S> http://rsdn.ru/Forum/Message.aspx?mid=701354&amp;only=1
Автор: Serginio1
Дата: 30.06.04


Посмотрел. Увы, там одномерный массив, с ним все ясно. А не можешь написать, как использовать unsafe и указатели, если массив именно двумерный и "кусочный". (т.е. float[][]) ? Что-то я не пойму, как тут указатели в C# использовать (см. мой оригинальный постинг)
With best regards
Pavel Dvorkin
Re[3]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 09:06
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, Pavel Dvorkin, Вы писали:


S>> Вообще то ты можешь содать свой хип для валуе типов содержащие только валуе типы.

S>> Пользуясь тем, что массывы более 80 кб не поддвергаются дефрагментации. И можешь на полную катушку использовать унсейв.
S>> Посмотри
S>> http://rsdn.ru/Forum/Message.aspx?mid=701354&amp;only=1
Автор: Serginio1
Дата: 30.06.04


PD>Посмотрел. Увы, там одномерный массив, с ним все ясно. А не можешь написать, как использовать unsafe и указатели, если массив именно двумерный и "кусочный". (т.е. float[][]) ? Что-то я не пойму, как тут указатели в C# использовать (см. мой оригинальный постинг)


Работай с указателями только через свой хип на больших массивах, используя тот факт, что они не дефрагментируютс и используешь
float**.
Там скорее всего проблема с проверкой выхода за пределы массива, с указателями таких проблем быть не должно.
Хотя это и извращение, но иногда овчинка стоит выделки, например для устранения райтбариера и представления списков в таком ввиде
http://www.rsdn.ru/Forum/?mid=445372
Автор: Serginio1
Дата: 17.11.03
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[4]: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 09:12
Оценка:
S> Работай с указателями только через свой хип на больших массивах, используя тот факт, что они не дефрагментируютс и используешь

Спасибо, это я понимаю. Да, собственно говоря, и результаты при расположении по столбцам вполне приличные по сранению с unmanaged code, даже очень. Мой вопрос не в этом — а именно для этого варианта что-то можно сделать ? Если не смогу я тначе хранить и не хочу все же в unsafe выходить ? Выход в unsafe — это все же, что ни говори, нарушение приличий, как мне тут долго и упорно объясняли.
With best regards
Pavel Dvorkin
Re[5]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 09:19
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


S>> Работай с указателями только через свой хип на больших массивах, используя тот факт, что они не дефрагментируютс и используешь


PD>Спасибо, это я понимаю. Да, собственно говоря, и результаты при расположении по столбцам вполне приличные по сранению с unmanaged code, даже очень. Мой вопрос не в этом — а именно для этого варианта что-то можно сделать ? Если не смогу я тначе хранить и не хочу все же в unsafe выходить ? Выход в unsafe — это все же, что ни говори, нарушение приличий, как мне тут долго и упорно объясняли.

Здесь проблема компилятора. Если в нативе ты можешь отключать проверку выхода за границы как в Delphi, то здесь все на усмотрение компилятора и во многих случаях не совсем удачно он просчитывает такие ситуации.
унсейв же так или иначе ипользуется, только на системном уровне и без него не все можно сделать.
Но снизить его использование до минимума вполне возможно.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[3]: тест с матрицами
От: GlebZ Россия  
Дата: 29.09.05 09:38
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, GlebZ, Вы писали:


S> По поводу [,] в новых бэттах не поправили ????


S> А насчет джагеттов то там скорее всего происходит проверка за границы. Опять как в новых версиях ????

Не знаю, сейчас времени не смотреть. А хотелось бы.

С уважением, Gleb.
Re: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 09:57
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

P
PD> {
PD> for(j = 0; j < nSize; j++)
PD> {
PD> temp = 0;
Вообщето можно слегка оптимизировать
float[] aa=a[i];
PD> for( k = 0; k < aa.Length; k++)
PD> temp += аа[k] * b[k][j];
PD> c[i][j] = temp;
PD> }
PD> }
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[2]: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 10:20
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Pavel Dvorkin, Вы писали:


S> Вообщето можно слегка оптимизировать


<skipped>

Нет, ничего здесь не изменится. Не в массиве a, а в массиве b здесь дело. Он плохо проходится — поперек шерсти . А с ним такая оптимизация не пройдет.
Массив а все равно нормально проходится.
Написал это и решил проверить. То же самое, 4 минуты 5 секунд.
With best regards
Pavel Dvorkin
Re[3]: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 10:23
Оценка:
Кстати, добавлю насчет требований по памяти

C++ — 12 Мб.
C# — 16 Мб.

Взято от Task Manager.

Нормально. Наезда не будет
With best regards
Pavel Dvorkin
Re[3]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 10:27
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Нет, ничего здесь не изменится. Не в массиве a, а в массиве b здесь дело. Он плохо проходится — поперек шерсти . А с ним такая оптимизация не пройдет.

PD>Массив а все равно нормально проходится.
PD>Написал это и решил проверить. То же самое, 4 минуты 5 секунд.
Всетаки компилятор оптимизировал доступ к а.
Значит не все так и плохо.
К b эта оптимизация сложнее.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[4]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 10:29
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Кстати, добавлю насчет требований по памяти


PD>C++ — 12 Мб.

PD>C# — 16 Мб.

PD>Взято от Task Manager.

Ты на таск манагер особо не смотри т.к. он показывает зарезервированную а не откоммиченную память.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[3]: тест с матрицами
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 29.09.05 10:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

Кстати а не проще перевернуть b, получишь все премущества DDR памяти ????
раз он квадратный
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[5]: тест с матрицами
От: Pavel Dvorkin Россия  
Дата: 29.09.05 10:51
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Ты на таск манагер особо не смотри т.к. он показывает зарезервированную а не откоммиченную память.


Извини, не согласен.

Task Manager — Help — Help Topics — memory usage, monitoring = Memory Using

the current working set of process in Kbytes. The current working set is the number of pages currently resident in memory.
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.