2009-03-23 2 views
10

Я пытаюсь найти контрпример к Pólya Conjecture, который будет где-то в 900 миллионов. Я использую очень эффективный алгоритм, который даже не требует какой-либо факторизации (аналогично сите из Eratosthenes, но с еще большей информацией. Поэтому требуется большой массив ints.Создание очень большого массива Java

Программа эффективна и правильна , но требует массив до xi, который нужно проверить (он проверяет все числа из (2, x)). Итак, если контрпример в 900 миллионов, мне нужен массив, который будет таким же большим. 't позвольте мне что-нибудь около 20 миллионов.Есть ли что-нибудь, что я могу сделать, чтобы получить массив, который большой?

+0

Можете ли вы объяснить, зачем нужен массив? Можете ли вы не использовать другую структуру данных, которая не обязательно должна быть в памяти сразу? – Apocalisp

+0

Каждое число в массиве равно 0. Каждый композит настроен так, чтобы содержать int наибольшего простого множителя композита (ex: 6 будет иметь 3). Все это выполняется очень быстро без какого-либо модуля или таких вычислений, но требует, чтобы все прошлые числа все еще находились в памяти (поэтому на них можно ссылаться). – 2009-03-23 17:27:02

+0

Другой алгоритм с двумя битами (для простых чисел и для нечетного числа простых коэффициентов) находит максимум 829 на 906316571 примерно за 4 минуты на моей машине. – starblue

ответ

2

Что вы подразумеваете под «не разрешаете». Вероятно, вы получаете OutOfMemoryError, поэтому добавьте больше памяти с опцией командной строки -Xmx.

+0

Да, пространство с кучей заканчивается. – 2009-03-23 16:56:00

13

Возможно, вы захотите увеличить максимальный размер кучи JVM. Вы можете сделать это с помощью параметра командной строки.

Я считаю, что это -Xmx3600m (3600 мегабайта)

-2

Используйте карту памяти файл (Java 5 NIO пакет) вместо этого. Или переместите сито в маленькую библиотеку C и используйте Java JNI.

+0

Я использую JVM теперь с -mx1024, и они, безусловно, используют все это. –

+0

Файл с отображением памяти все еще должен быть достаточно мал, чтобы вписаться в физическое адресное пространство. –

+0

@Mike: Вы имеете в виду, что отображаемый вид должен быть достаточно мал, чтобы вместить его в физическое адресное пространство (в Win32 это означает непрерывную необработанную ОЗУ). Сам файл может неограниченно расширяться до размера свободного места на диске. – codekaizen

6

Если вам не нужно все это загружать в память сразу, вы можете сегментировать его в файлы и хранить на диске.

10

Java предоставит до 2 миллиардов записей массива. Это ваша машина (и ваша ограниченная память), которая не может справиться с такой большой суммой.

+1

Это 'Integer.MAX_VALUE' или это' Integer.MAX_VALUE - 1' (из-за пределов ubound)? – Pacerier

+2

Последний раз, когда я проверил 'Integer.MAX_VALUE', все еще был самый большой' int', а индекс последнего элемента был 'n - 1'. Я не вижу здесь проблемы. – Bombe

+0

http://stackoverflow.com/questions/3038392/do-java-arrays-have-a-maximum-size это на самом деле 'Integer.MAX_VALUE - 5' – Flimm

1

Вы можете определить свой собственный класс, который хранит данные в массиве 2d, который будет ближе к sqrt (n) по sqrt (n). Затем используйте индексную функцию для определения двух индексов массива. При необходимости это можно расширить до большего размера.

Основная проблема, с которой вы столкнетесь, заканчивается из ОЗУ. Если вы подходите к этому пределу, вам нужно переосмыслить свой алгоритм или рассмотреть внешнее хранилище (то есть файл или базу данных).

7

900 миллионов 32-битных ints без дополнительных накладных расходов - и всегда будет больше накладных расходов - потребуется чуть более 3,35 гигабайта. Единственный способ получить эту большую память - с 64-разрядной JVM (на машине с объемом памяти не менее 8 ГБ) или использовать некоторый кеш с поддержкой дисков.

1

Если ваш алгоритм позволяет это:

  • Вычислите это в срезах, которые вписываются в память.

    Вам нужно будет переделать вычисления для каждого фрагмента, но он будет достаточно быстрым.

  • Используйте массив меньшего числового типа, например байт.

0

Я написал версию сита Эратосфена для Project Euler, которая работала на кусках пространства поиска за раз. Он обрабатывает первые целые числа 1M (например), но сохраняет каждое простое число, которое он находит в таблице. После того, как вы повторили все найденные до сих пор простые числа, массив повторно инициализируется, и найденные пробелы уже используются для обозначения массива перед поиском следующего.

Таблица отображает штрих в его «смещение» от начала массива для следующей итерации обработки.

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

Этот метод также обеспечивает memoisation для последующих итераций по простым числам. Это быстрее, чем сканирование вашей редкой ситовой структуры данных, которая ищет их каждый раз.

+0

в моем случае, неправа не являются только 0, но содержат наибольшие простые множители. Таким образом, я могу найти количество простых чисел без фактического распределения чисел. Композиты почти так же важны, как простые в этом случае. – 2009-03-23 17:38:48

+0

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

0

I вторая идея @ sfossen и @Aaron Digulla. Я бы пошел на доступ к диску. Если ваш алгоритм может использовать интерфейс List, а не простой массив, вы можете написать адаптер из списка в файл с отображением памяти.

0

Используйте шкаф Tokyo Cabinet, Berkeley DB или любой другой дисковый накопитель на основе ключей. Они быстрее, чем любая обычная база данных, но позволяют использовать диск вместо памяти.

0

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

0

Вы могли бы получить с помощью 900 миллионов бит? (возможно, хранится как массив байтов).

10

Массивы Java индексируются по int, поэтому массив не может превышать 2^31 (нет целых без подписи). Таким образом, максимальный размер массива - 2147483648, который потребляет (для простого int []) 8589934592 байта (= 8 ГБ).

Таким образом, int-index обычно не является ограничением, так как в любом случае у вас не хватит памяти.

В вашем алгоритме вместо этого вы должны использовать Список (или карту) в качестве своей структуры данных и выбрать реализацию списка (или карты), которая может вырасти выше 2^31. Это может стать сложным, поскольку «обычная» реализация ArrayList (и HashMap) использует внутренние массивы. Вам нужно будет реализовать пользовательскую структуру данных; например используя 2-уровневый массив (список/массив). Когда вы на нем, вы также можете попытаться упаковать бит более плотно.

1

Для эффективного хранящимся больших массивов примитивов (булево, байт, ... удвоится рекомендую наши JLargeArrays библиотеки доступны на GitHub (https://github.com/IcmVis/JLargeArrays) - она ​​сохраняет произвольные большие массивы, обеспечивающие достаточный объем памяти доступен, например, 12G байтовый массив на 16 GB PC, испытано на Oracle и IBM JVM, с хорошей многопоточной эффективностью.

-1

Вы можете попробовать разделив его на несколько массивов.

for(int x = 0; x <= 1000000; x++){ 
    myFirstList.add(x); 
} 
for(int x = 1000001; x <= 2000000; x++){ 
    mySecondList.add(x); 
} 

затем итерацию над ними.

for(int x: myFirstList){ 
    for(int y: myFirstList){ 
     //Remove multiples 
    } 
} 
//repeat for second list 
Смежные вопросы