После того, как мне здесь объяснили, что я ничего не понимаю , ушел я с горя в "Философию" и ответил там на одно сообщение, прямого отношения к тематике этого форума не имеющее. Однако черт меня угораздил там мимоходом упомянуть C#, в результате чего Sinclair нашел меня и там (http://www.rsdn.ru/Forum/Message.aspx?mid=1404835&only=1
) и продолжил объяснять мне, что я ничего не понимаю. И состоялась у нас вот такая дискуссия
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 можно применить только к массивам из простых типов, а здесь все же массив массивов.
Вообще то ты можешь содать свой хип для валуе типов содержащие только валуе типы.
Пользуясь тем, что массывы более 80 кб не поддвергаются дефрагментации. И можешь на полную катушку использовать унсейв.
Посмотри http://rsdn.ru/Forum/Message.aspx?mid=701354&only=1
При чем создание хиппа под структуры определенного размера вещь тривиальная и активно используется в том же в нативе, для более выстрого выделения памяти и освобождения.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, 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 секунд.
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали:
S> Вообще то ты можешь содать свой хип для валуе типов содержащие только валуе типы. S> Пользуясь тем, что массывы более 80 кб не поддвергаются дефрагментации. И можешь на полную катушку использовать унсейв. S> Посмотри S> http://rsdn.ru/Forum/Message.aspx?mid=701354&only=1
Посмотрел. Увы, там одномерный массив, с ним все ясно. А не можешь написать, как использовать unsafe и указатели, если массив именно двумерный и "кусочный". (т.е. float[][]) ? Что-то я не пойму, как тут указатели в C# использовать (см. мой оригинальный постинг)
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Serginio1, Вы писали:
S>>Здравствуйте, Pavel Dvorkin, Вы писали:
S>> Вообще то ты можешь содать свой хип для валуе типов содержащие только валуе типы. S>> Пользуясь тем, что массывы более 80 кб не поддвергаются дефрагментации. И можешь на полную катушку использовать унсейв. S>> Посмотри S>> http://rsdn.ru/Forum/Message.aspx?mid=701354&only=1
PD>Посмотрел. Увы, там одномерный массив, с ним все ясно. А не можешь написать, как использовать unsafe и указатели, если массив именно двумерный и "кусочный". (т.е. float[][]) ? Что-то я не пойму, как тут указатели в C# использовать (см. мой оригинальный постинг)
Работай с указателями только через свой хип на больших массивах, используя тот факт, что они не дефрагментируютс и используешь
float**.
Там скорее всего проблема с проверкой выхода за пределы массива, с указателями таких проблем быть не должно.
Хотя это и извращение, но иногда овчинка стоит выделки, например для устранения райтбариера и представления списков в таком ввиде http://www.rsdn.ru/Forum/?mid=445372
S> Работай с указателями только через свой хип на больших массивах, используя тот факт, что они не дефрагментируютс и используешь
Спасибо, это я понимаю. Да, собственно говоря, и результаты при расположении по столбцам вполне приличные по сранению с unmanaged code, даже очень. Мой вопрос не в этом — а именно для этого варианта что-то можно сделать ? Если не смогу я тначе хранить и не хочу все же в unsafe выходить ? Выход в unsafe — это все же, что ни говори, нарушение приличий, как мне тут долго и упорно объясняли.
S>> Работай с указателями только через свой хип на больших массивах, используя тот факт, что они не дефрагментируютс и используешь
PD>Спасибо, это я понимаю. Да, собственно говоря, и результаты при расположении по столбцам вполне приличные по сранению с unmanaged code, даже очень. Мой вопрос не в этом — а именно для этого варианта что-то можно сделать ? Если не смогу я тначе хранить и не хочу все же в unsafe выходить ? Выход в unsafe — это все же, что ни говори, нарушение приличий, как мне тут долго и упорно объясняли.
Здесь проблема компилятора. Если в нативе ты можешь отключать проверку выхода за границы как в Delphi, то здесь все на усмотрение компилятора и во многих случаях не совсем удачно он просчитывает такие ситуации.
унсейв же так или иначе ипользуется, только на системном уровне и без него не все можно сделать.
Но снизить его использование до минимума вполне возможно.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, GlebZ, Вы писали:
S> По поводу [,] в новых бэттах не поправили ????
S> А насчет джагеттов то там скорее всего происходит проверка за границы. Опять как в новых версиях ????
Не знаю, сейчас времени не смотреть. А хотелось бы.
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали:
S> Вообщето можно слегка оптимизировать
<skipped>
Нет, ничего здесь не изменится. Не в массиве a, а в массиве b здесь дело. Он плохо проходится — поперек шерсти . А с ним такая оптимизация не пройдет.
Массив а все равно нормально проходится.
Написал это и решил проверить. То же самое, 4 минуты 5 секунд.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Нет, ничего здесь не изменится. Не в массиве a, а в массиве b здесь дело. Он плохо проходится — поперек шерсти . А с ним такая оптимизация не пройдет. PD>Массив а все равно нормально проходится. PD>Написал это и решил проверить. То же самое, 4 минуты 5 секунд.
Всетаки компилятор оптимизировал доступ к а.
Значит не все так и плохо.
К b эта оптимизация сложнее.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Кстати, добавлю насчет требований по памяти
PD>C++ — 12 Мб. PD>C# — 16 Мб.
PD>Взято от Task Manager.
Ты на таск манагер особо не смотри т.к. он показывает зарезервированную а не откоммиченную память.
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня