none
Массив больше 2-х гигов? RRS feed

Ответы

  • Мои измерения показывают что скорость даже несколько выше чем при использовании обычного массива. Но конечно выход за пределы массива очевидно приведет к AV.

    Для отладки можно использовать первый вариант возвращая его вместо Ptr.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Для 1024 * 1024 * 1024 интов можно использовать одномерный массив int [] intArray;

    и потерь в производительности не будет. Вот например для 0x7fffffff интов потребуется

    двумерный массив int [][] intRebelled; что заставит нас при каждом get, set метаться с вопросом - где я?

    в нулевом массиве или в n-м - потеря производительности в 3,6 раз, проверял.

    Вообще говоря массив int[][] не двумерный, а массив массивов (jagged array). Двумерный массив будет int[,].

    В любом случае попробуйте код выше с указателем. Я без проблем аллокировал массив байтов из 6 миллардов элементов (на домашнем компьютере всего 8ГБ).

    Сравнение скорости с обычным массивом (размер конечно был одинаков и меньше максимального числа элементов) показал примерно 20% уменьшение времени доступа (550-600 мс против 650-750 мс на байтовых массивах 1 ГБ. Измерения конечно в release и без отладчика.

    Метод будет работать с любым типом который занимает один непрерывный участок памяти - byte, int, long, float, double и т.п. плюс структуры состоящие из таких типов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа ToylexNet 5 января 2015 г. 9:43
    4 января 2015 г. 19:25
    Модератор

Все ответы

  • Простите что пишу не по теме, но можно "физический" смысл одномерного массива на 2  гигабайта. Просто не могу представить для чего такое нужно так "хламить" память. Пожалуйста, пример если можно...
    3 января 2015 г. 19:45
  • Пожалуйста:

    var hugeArray = new int[1 * 1024 * 1024 *1024]; // Массив размером в 4 ГБ.

    Не забудьте разрешить объекты более 2 ГБ в app.config:

    <configuration>
      <runtime>
        <gcAllowVeryLargeObjects enabled="true" />
      </runtime>  

    ..

    Так же помните что есть ограничение на число элементов в массиве (2^32).


    This posting is provided "AS IS" with no warranties, and confers no rights.

    3 января 2015 г. 19:45
    Модератор
  • Так же помните что есть ограничение на число элементов в массиве (2^32).
    Для одномерных массивов эффективное ограничение на число элементов будет в два раза меньше из-за ограничения на максимальный индекс.
    Using this element in your application configuration file enables arrays that are larger than 2 GB in size, but does not change other limits on object size or array size:
    • The maximum number of elements in an array is UInt32.MaxValue.
    • The maximum index in any single dimension is 2,147,483,591 (0x7FFFFFC7) for byte arrays and arrays of single-byte structures, and 2,146,435,071 (0X7FEFFFFF) for other types.
    • The maximum size for strings and other non-array objects is unchanged.
    <gcAllowVeryLargeObjects> Element
    • Изменено PetSerAl 3 января 2015 г. 21:17
    • Помечено в качестве ответа ToylexNet 3 января 2015 г. 22:17
    • Снята пометка об ответе ToylexNet 5 января 2015 г. 9:43
    3 января 2015 г. 20:57
  • Простите что пишу не по теме, но можно "физический" смысл одномерного массива на 2  гигабайта. Просто не могу представить для чего такое нужно так "хламить" память. Пожалуйста, пример если можно...

    Некоторые математики при использовании численных методов любят запихать в одномерный или двумерный массив много - много чисел. Физики тоже этим грешат. Да и химики, в общем - то. Про биологов не знаю.

    3 января 2015 г. 21:42
  • int [] largeArray = new int[1<<30]; точнее

    Это все?

    Мне нужно Huge Array, например, 20 и больше гигов массив чтобы.

    Такое возможно или нет? Сейчас я это делаю через танцы с бубном...

    3 января 2015 г. 21:51
  • Простите что пишу не по теме, но можно "физический" смысл одномерного массива на 2  гигабайта. Просто не могу представить для чего такое нужно так "хламить" память. Пожалуйста, пример если можно...

    Некоторые математики при использовании численных методов любят запихать в одномерный или двумерный массив много - много чисел. Физики тоже этим грешат. Да и химики, в общем - то. Про биологов не знаю.

    Совершенно верно - "при использовании численных методов". 

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

    Паралелить нет возможности - накопительный опыт...

    3 января 2015 г. 22:04
  • О, кстати long работает

    long [] LargeArray = new long[1<<30];

    LargeArray !! 8 gb

    и структура:

    struct any { byte b0, ..... bn };

    any [] HugeArray = new any[1<<30];

    Поспешил радоваться, 1<<30 максимальное значение, это проблема,

    а надо 1<<40.... и т.п.

    • Изменено ToylexNet 3 января 2015 г. 22:24
    3 января 2015 г. 22:12
  • Так вам массив больше 2 ГБ или число эленентов больше ~2 миллиардов? Это не одно и то же.

    Если первое то см. выше. Чем больше размер элемента тем больше может быть массив.

    Если второе то придется использовать врапперы которые имеют несколько подмассивов или используют указатели. Что то в этом роде:

    using System;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1
    {
        public unsafe class HugeArray: IDisposable
        {
            private IntPtr _ptr;
            private readonly ulong _elementCount;
    
            public HugeArray(ulong elementCount)
            {
                _elementCount = elementCount; 
                
                _ptr = Marshal.AllocHGlobal((IntPtr) (elementCount * sizeof(byte)));
            }
    
            ~HugeArray()
            {
                Dispose();
            }
    
            public ulong Count
            {
                get
                {
                    return _elementCount;
                }
            }
    
            public byte this[ulong index]
            {
                get
                {
                    if (index < _elementCount)
                    {
                        return *((byte*)_ptr + index);
                    }
    
                    throw new IndexOutOfRangeException();
                }
                set
                {
                    if (index >= _elementCount)
                    {
                        throw new IndexOutOfRangeException();
                    }
    
                    *((byte*)_ptr + index) = value;
                }
            }
    
            public void Dispose()
            {
                if (_ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(_ptr);
    
                    _ptr = IntPtr.Zero;
                }
            }
        }
    }
    

    Что до 1<<40 то это весьма немало. Многие версии ОС столько просто не поддерживают. Да и при обработке массивов таких размеров реально нужны кластеры. Просто на то чтоб "потогать" 1<<40 элементов уйдет немало времени.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    4 января 2015 г. 0:08
    Модератор
  • Простите что пишу не по теме, но можно "физический" смысл одномерного массива на 2  гигабайта. Просто не могу представить для чего такое нужно так "хламить" память. Пожалуйста, пример если можно...

    Некоторые математики при использовании численных методов любят запихать в одномерный или двумерный массив много - много чисел. Физики тоже этим грешат. Да и химики, в общем - то. Про биологов не знаю.

    Совершенно верно - "при использовании численных методов". 

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

    Паралелить нет возможности - накопительный опыт...

    Ясно. Спасибо за ликбез. Теперь поняла. Лень придумывать рекурсивные алгоритмы расчетов, проще линейные,  так как алгоритмы одноразовые и время на разработку рекурсивного алгоритма будет в разы больше чем обработка большого массива данных прямым перебором. Сама этим иногда грешу, если знаю что алгоритм одноразовый.
    4 января 2015 г. 5:46
  • Алогоритмы тут не при чем, иногда сами данные требуемые для решения занимают больший объем. Примерами могут послужить задачи в области электростатики, термодинамики и сопротивления материалов.

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

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


    This posting is provided "AS IS" with no warranties, and confers no rights.

    4 января 2015 г. 7:04
    Модератор
  • Алогоритмы тут не при чем, иногда сами данные требуемые для решения занимают больший объем. Примерами могут послужить задачи в области электростатики, термодинамики и сопротивления материалов.

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

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


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Простите, я никого не хотела обидеть. Я простая представительница программистов из деревни. И смотрю на мир со своей маленькой колокольни. Мне чужды термодинамика, электростатика и прочее. Просто иногда мне вспоминается способ вычисления интеграла функции терпящей разрывы методом Монте Карло, который позволяет "забить" на вычисление значение интеграла классическим способом, а добиться результата менее точным, но более простым и менее ресурсоемким способом. Еще раз прошу прощения, если мои высказывания кого-то обидели.
    4 января 2015 г. 7:47

  • using System;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1
    {
        public unsafe class HugeArray: IDisposable
        {
            private IntPtr _ptr;
            private readonly ulong _elementCount;
    
            public HugeArray(ulong elementCount)
            {
                _elementCount = elementCount; 
                
                _ptr = Marshal.AllocHGlobal((IntPtr) (elementCount * sizeof(byte)));
            }
    
            ~HugeArray()
            {
                Dispose();
            }
    
            public ulong Count
            {
                get
                {
                    return _elementCount;
                }
            }
    
            public byte this[ulong index]
            {
                get
                {
                    if (index < _elementCount)
                    {
                        return *((byte*)_ptr + index);
                    }
    
                    throw new IndexOutOfRangeException();
                }
                set
                {
                    if (index >= _elementCount)
                    {
                        throw new IndexOutOfRangeException();
                    }
    
                    *((byte*)_ptr + index) = value;
                }
            }
    
            public void Dispose()
            {
                if (_ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(_ptr);
    
                    _ptr = IntPtr.Zero;
                }
            }
        }
    }

    Что до 1<<40 то это весьма немало. Многие версии ОС столько просто не поддерживают. Да и при обработке массивов таких размеров реально нужны кластеры. Просто на то чтоб "потогать" 1<<40 элементов уйдет немало времени.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Да, примерно такой бубен, только другими словами, я использую.

    Данных от 15 гигов, т.е. 2^4 * 2^30 = 2^34...

    c 40, конечно, погорячился.

    В таком виде производительность падает в три раза, к сожалению.

    4 января 2015 г. 12:10
  • This posting is provided "AS IS" with no warranties, and confers no rights.

    Простите, я никого не хотела обидеть. Я простая представительница программистов из деревни. И смотрю на мир со своей маленькой колокольни. Мне чужды термодинамика, электростатика и прочее. Просто иногда мне вспоминается способ вычисления интеграла функции терпящей разрывы методом Монте Карло, который позволяет "забить" на вычисление значение интеграла классическим способом, а добиться результата менее точным, но более простым и менее ресурсоемким способом. Еще раз прошу прощения, если мои высказывания кого-то обидели.

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

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


    • Изменено ToylexNet 4 января 2015 г. 12:44
    4 января 2015 г. 12:29
  • ToylexNet<abbr class="affil"></abbr> Вы меня совершенно не знаете, я не фанатка майкрософта. Ну нас, программистов, на парах дискретной математики заставляли изучать различные способы достижения результата. Нами в частности изучался "Простейший метод Монте-Карло для вычисления интеграла", я его запомнила из-за того, что у любой задачи есть множество решений. Если классические методы бессильны или ими не возможно воспользоваться из-за их громоздкости, то есть и другие способы решения проблем.

    Еще один прикол из жизни про выбор решения... Мы на высшей математике начали изучать пределы. И тут препод по философии с нас прикололся задал задачку: "Из пункта А в пункт В вышел поезд со скоростью 100 км/ч, а на встречу ему из пункта В в пункт А вылетела ласточка со скоростью 150 км/ч. Как только ласточка встречалась с поездом, она разворачивалась и летела обратно в пункт В, долетала до пункта В и вновь летела на встречу поезду и так до тех пор пока поезд не приедет в пункт В. Сколько налетала ласточка, если расстояние между пунктами 300 км." Все как один начали решать эту задачу через пределы, поезд стремится к пункту В, и ласточка как маятник будет совершать множество разворотов, пройденные расстояния ласточкой будут стремится к нулю... Ну и так далее рассуждения в том же духе... Пятикласник решит эту задачу за пару минут и то их потратит на оформление задачи, так как задача решается в два действия...

    А в вас гибнет писатель романтик... "...развевающимися на ветру волосами и легкими такими воспоминаниями..." Спасибо, я давно не слышала о себе таких лестных слов...

    4 января 2015 г. 15:56

  • Да, примерно такой бубен, только другими словами, я использую.

    Данных от 15 гигов, т.е. 2^4 * 2^30 = 2^34...

    c 40, конечно, погорячился.

    В таком виде производительность падает в три раза, к сожалению.

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

    Попробуйте использовать указатели на прямую:

        public unsafe class HugeArray: IDisposable
        {
            private readonly byte* _ptrByte;
            private IntPtr _ptr;
            private readonly ulong _elementCount;
    
            public HugeArray(ulong elementCount)
            {
                _elementCount = elementCount; 
                
                _ptr = Marshal.AllocHGlobal((IntPtr) (elementCount * sizeof(byte)));
    
                _ptrByte = (byte*)_ptr;
            }
    
            ~HugeArray()
            {
                Dispose();
            }
    
            public byte* Ptr
            {
                get { return _ptrByte; }
            }
    
            public ulong Count
            {
                get
                {
                    return _elementCount;
                }
            }        
    
            public void Dispose()
            {
                if (_ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(_ptr);
    
                    _ptr = IntPtr.Zero;
                }
            }
    

    Использование вполне естественное, разве что появляется словечко unsafe в декларации метода:

                var size = (ulong)4 * 1024 * 1024 * 1024;
    
                var hugeArray = new HugeArray(size);
    
                hugeArray.Ptr[0] = 10;
    
                hugeArray.Ptr[size - 1] = 55;
    
                var sw = new Stopwatch();
    
                sw.Start();            
    
                for (ulong i = 0; i < size; i++)
                {
                    hugeArray.Ptr[i] = 55;
                }
    
                sw.Stop();
    
                Console.WriteLine("Huge: {0}", sw.ElapsedMilliseconds);
    

    Мои измерения показывают что скорость даже несколько выше чем при использовании обычного массива. Но конечно выход за пределы массива очевидно приведет к AV.

    Для отладки можно использовать первый вариант возвращая его вместо Ptr.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    4 января 2015 г. 18:02
    Модератор
  • А в вас гибнет писатель романтик... "...развевающимися на ветру волосами и легкими такими воспоминаниями..." Спасибо, я давно не слышала о себе таких лестных слов...

    300/100*150 или 150/100*300

    И да, я C# писатель романтик.. а Вас хотел слегка взбодрить и мне это удалось..


    • Изменено ToylexNet 4 января 2015 г. 18:26
    4 января 2015 г. 18:25
  • И да, я C# писатель романтик.. а Вас хотел слегка взбодрить и мне это удалось..
    Спасибо! Но давайте не будем отвлекать людей от темы.
    4 января 2015 г. 18:42
  • Мои измерения показывают что скорость даже несколько выше чем при использовании обычного массива. Но конечно выход за пределы массива очевидно приведет к AV.

    Для отладки можно использовать первый вариант возвращая его вместо Ptr.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Для 1024 * 1024 * 1024 интов можно использовать одномерный массив int [] intArray;

    и потерь в производительности не будет. Вот например для 0x7fffffff интов потребуется

    двумерный массив int [][] intRebelled; что заставит нас при каждом get, set метаться с вопросом - где я?

    в нулевом массиве или в n-м - потеря производительности в 3,6 раз, проверял.

    4 января 2015 г. 18:52
  • А приятно видеть здесь представителей программистов из деревни
    с развевающимися на ветру волосами с серпом и молотом в руках...
    Романтика, однако...
    4 января 2015 г. 18:55
  • Мои измерения показывают что скорость даже несколько выше чем при использовании обычного массива. Но конечно выход за пределы массива очевидно приведет к AV.

    Для отладки можно использовать первый вариант возвращая его вместо Ptr.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Для 1024 * 1024 * 1024 интов можно использовать одномерный массив int [] intArray;

    и потерь в производительности не будет. Вот например для 0x7fffffff интов потребуется

    двумерный массив int [][] intRebelled; что заставит нас при каждом get, set метаться с вопросом - где я?

    в нулевом массиве или в n-м - потеря производительности в 3,6 раз, проверял.

    Вообще говоря массив int[][] не двумерный, а массив массивов (jagged array). Двумерный массив будет int[,].

    В любом случае попробуйте код выше с указателем. Я без проблем аллокировал массив байтов из 6 миллардов элементов (на домашнем компьютере всего 8ГБ).

    Сравнение скорости с обычным массивом (размер конечно был одинаков и меньше максимального числа элементов) показал примерно 20% уменьшение времени доступа (550-600 мс против 650-750 мс на байтовых массивах 1 ГБ. Измерения конечно в release и без отладчика.

    Метод будет работать с любым типом который занимает один непрерывный участок памяти - byte, int, long, float, double и т.п. плюс структуры состоящие из таких типов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа ToylexNet 5 января 2015 г. 9:43
    4 января 2015 г. 19:25
    Модератор
  • Кстати о скорости доступа к элементам массивов разных типов и
    различного порядка обращения, что имеет существенное значение

    Тип массива и порядок присвоения......................................Среднее время, нс
    for(i=0;i<1000000000;i++) B[i]=1;.............................................1.3
    for(i=0;i<1000;i++) for(j=0;j<1000000;j++) B[i][j]=1;........4
    for(j=0;j<1000000;j++) for(i=0;i<1000;i++) B[i][j]=1;........150
    for(i=0;i<1000;i++) for(j=0;j<1000000;j++) B[i,j]=1;.........11
    for(j=0;j<1000000;j++) for(i=0;i<1000;i++) B[i,j]=1;.........40



    • Изменено QazRdx 5 января 2015 г. 0:08
    4 января 2015 г. 22:33
  • Что то многовато. У меня вышло около 0.7 нс на байт на обычном массиве и ближе к 0.5 нс/байт через указатель, см. код выше. Двумерный массив мало отличается от обычного, примерно 0.8 нс/ байт.

    Правда память DDR4 и процессор последнего поколения, но не думаю что это объяснит разницу в 10 и более раз. Тем более что на байтах память не является узким местом.

    Возможно условия тестирования разные. Как я уже говорил тестировать следует в релизе (с оптимизацией)  и без отладчика (так как JIT при наличии отладчика генерирует совсем другой код). 

    Так же перед циклом измерения следует "тронуть" массив чтоб память была реально выделена (на что может уйти дополнительное время).


    This posting is provided "AS IS" with no warranties, and confers no rights.

    4 января 2015 г. 23:58
    Модератор
  • Да, я подправил.
    5 января 2015 г. 0:10
  • Попробуем свериться?

    Мой компьютер - 
    AMD E-450 APU with Radeon (tm) HD Graphics 1.65 GHz,
    2 Cores, 2 Logical,
    4.00 GB (3.8 GB usable),
    64-bit Operating System,
    Win 7 Home Premium SP1,
    MSVS Express 2013,
    .NET Framework 4.5.50938,
    C# 2013

    Настройки -
    Проект - Свойства - Сборка :
    Конфигурация - Release,
    Конечная платформа - AnyCPU,
    v.....Предпочтительно: 32-разрядн.
    v.....Оптимизировать код

    Тест -
    using System;
    namespace ArrSpeedTest
    {	class Program 
    	{	static void Main(string[] args)
    		{	int N=1000000, n=1000,i,j,k;
    			double d = 0;
    			DateTime t;
    			byte [][]	B =	new byte [1000][];
    			for	(	i=0;i<n;i++)	B[i] = new byte [1000000];
    			for	(	k=0;k<5;k++	)
    			{	t	=	DateTime.Now;
    try			{	for (i=0;i<N;i++)
    					for	(j=0;j<n;j++)
    						B[j][i]=1;
    				d	=	(	DateTime.Now-t).TotalMilliseconds * 1000 / N/	n;
    			}
    catch		(	Exception e	){	Console.WriteLine	(	e.ToString());	}
    				Console.WriteLine	(	"d = " + d.ToString ("F6") + " мкс"	);
    }	}	}	}		//	d	=	0.1580 мкс	= 150 нс









    • Изменено QazRdx 5 января 2015 г. 1:39
    5 января 2015 г. 1:29
  • Ну уж тогда убрать "Предпочтительно: 32-разрядн", иначе код будет выполняться в 32 битном режиме. В любом случае машины слишком разные чтоб можно было объективно сравнивать.

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


    This posting is provided "AS IS" with no warranties, and confers no rights.

    5 января 2015 г. 1:53
    Модератор
  • 32-бита убрал - без изменения.
    Это у меня для облака, там 32-битная машина.

    "...эффект от перестановки индексов..."
    - да, занятненькое явленьице.
    Опросы массивов ВСЕХ типов и в зависимости от ПОРЯДКА ОПРОСА
    ЗНАЧИТЕЛЬНО РАЗНЯТСЯ по времени доступа.

    "Есть о чем подумать при работе с большими массивами"
    - и с маленькими, как у меня, но с частым обращением к ним, тоже.

    Но самое интересное вот это -

    for(j=0;j<1000000;j++) for(i=0;i<1000;i++) {m=j*1000+i;............B[m]=1; }......~15нс
    for(j=0;j<1000;j++) for(i=0;i<1000000;i++) {m=j*1000000+i;.....B[m]=1; }......~15нс

    Т.е. по-видимому, индексы в двумерном массиве вычисляются именно так.
    Но не понятно, почему, в примерах 4 и 5
    при смене индексации происходит такое значительное замедление?
    В одномерном-то массиве этого не происходит, согласно второму примеру в этом сообщении.





    • Изменено QazRdx 5 января 2015 г. 6:55
    5 января 2015 г. 6:44
  • Мои измерения показывают что скорость даже несколько выше чем при использовании обычного массива. Но конечно выход за пределы массива очевидно приведет к AV.

    Для отладки можно использовать первый вариант возвращая его вместо Ptr.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Для 1024 * 1024 * 1024 интов можно использовать одномерный массив int [] intArray;

    и потерь в производительности не будет. Вот например для 0x7fffffff интов потребуется

    двумерный массив int [][] intRebelled; что заставит нас при каждом get, set метаться с вопросом - где я?

    в нулевом массиве или в n-м - потеря производительности в 3,6 раз, проверял.

    Вообще говоря массив int[][] не двумерный, а массив массивов (jagged array). Двумерный массив будет int[,].

    В любом случае попробуйте код выше с указателем. Я без проблем аллокировал массив байтов из 6 миллардов элементов (на домашнем компьютере всего 8ГБ).

    Сравнение скорости с обычным массивом (размер конечно был одинаков и меньше максимального числа элементов) показал примерно 20% уменьшение времени доступа (550-600 мс против 650-750 мс на байтовых массивах 1 ГБ. Измерения конечно в release и без отладчика.

    Метод будет работать с любым типом который занимает один непрерывный участок памяти - byte, int, long, float, double и т.п. плюс структуры состоящие из таких типов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

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

    5 января 2015 г. 9:41
  • Всем привет!
    Пришлось вернуться - появился большой массив.
    Не хочет моя система принимать HugeArray -
    "Небезопасный код может использоваться только
    при компиляции с параметром /unsafe"
    Но unsafe-то есть в самом начале программы,
    чего же ей не хватает?

    using System;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    
    namespace BigArray
    {	public	unsafe	class		HugeArray	:	IDisposable
    	{	private readonly byte* _ptrByte;
    		private		IntPtr		_ptr;
    		private		readonly	ulong	_elementCount;
    		public		HugeArray(	ulong 	elementCount	)
    		{	_elementCount	=	elementCount; 
    			_ptr	=	Marshal.AllocHGlobal((IntPtr) (elementCount * sizeof(byte)));
    			_ptrByte = (byte*)_ptr;
    		}
    		~HugeArray()		{	Dispose();	}
    		public byte* Ptr	{	get		{	return	_ptrByte;				}	}
    		public ulong Count	{	get		{	return	_elementCount;	}	}        
    		public void Dispose()
    		{	if		(	_ptr != IntPtr.Zero)
    			{	Marshal.FreeHGlobal(_ptr);
    				_ptr = IntPtr.Zero;
    		}	}
    		static void Main	(	string[] args	)
    		{	var size = (ulong)4 * 1024 * 1024 * 1024;
    			var hugeArray = new HugeArray(size);
    			hugeArray.Ptr[0] = 10;
    			hugeArray.Ptr[size - 1] = 55;
    			var sw = new Stopwatch();
    			sw.Start();            
    			for (ulong i = 0; i < size; i++)	hugeArray.Ptr[i] = 55;
    			sw.Stop();
    			Console.WriteLine("Huge: {0}", sw.ElapsedMilliseconds);
    }	}	}






    • Изменено QazRdx 7 мая 2016 г. 19:53
  • Сорри!
    Нашел...
    https://msdn.microsoft.com/ru-ru/library/ct597kb0.aspx
  • > я тоже наблюдаю эффект от перестановки индексов. Я думаю обращение к элементам в разных участках памяти гарантированно трашит кэш. Есть о чем подумать при работе с большими массивами.

    Ilya Tumanov совершенно верно отметил, что происходят промахи кэша (cache miss).

    Очень рекомендую ознакомиться с этой статьёй: Оптимизация циклов: нужны блоки - и повторить из неё код. Благодаря грамотному использованию кэша скорость возрастает в несколько раз, в том числе и на C#.

    Также рекомендую статью RAM - не RAM, или Cache-Conscious Data Structures. Принцип Hot/Cold легко использовать на практике (хотя он может нарушить принципы ООП, например).

    Ну и на заедочку ссылка на Вики: Locality of reference. И по ссылкам, по ссылкам!..

    К сожалению, на русском материалов намного меньше, чем на английском.

    А в целом, .NET всё-таки не предназначен для написания числомолотилок.