Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.83.87.94] |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
В общем, решил проблему структурой с кучей массивов по 2^23.
Задав похожие вопросы в других местах - люди ни на одном ПК не могли получить больше 2^27. Питон преуспел в этом больше всех. |
Сообщ.
#17
,
|
|
|
Цитата Сергей85 @ люди ни на одном ПК не могли получить больше 2^27. 227*8 = 1 Гб - для 32-битного приложения это нормально. А вот 223*8 - явно мало. Либо у тебя какие-то левые dll рубят все свободное АП на несколько малых кусков (что мало вероятно), либо ты сам со своими массивами где-то косячишь (что более вероятно). Все это можно легко проверить с помощью VMMap (запустить, сохранить отчет в txt и выложить сюда). |
Сообщ.
#18
,
|
|
|
Цитата leo @ Косячит хренова тонна программистов, попробовавших ПРОСТО СОЗДАТЬ массив 2^25? Я уже пишу не от лица 1 человека, а от 10-ти. |
Сообщ.
#19
,
|
|
|
Сообщ.
#20
,
|
|
|
Картинки VMMap ты привел совершенно не информативные. На них даже параметр Free\Largest block не виден, не говоря уже о занятых адресах (нужно хотя бы прокрутить нижний список до перехода адресов с 0ххх.. на Хххх..., чтобы увидеть причину фрагментации АП). Но лучше не картинки приводить, а сохранить данные VMMap через File\Save as в формате mmp и выложить их сюда, чтобы можно было увидеть всю картину\карту распределения памяти
Пример: в Excel 2002 пишу аналогичный макрос: массив 2^26 выделяет нормально, 2^27 - облом. Смотрю в VMMap и вижу причину - максимальный свободный блок составляет всего 688 Мб, прокручиваю адреса до перехода с 0ххх.. на Хххх.. и вижу, что причина в самом Excel.exe и прочих приблудах Office, которые грузятся по адресам ~300.. и рубят свободный блок АП ~1.4 Гб примерно пополам. Цитата Сергей85 @ Косячит хренова тонна программистов, попробовавших ПРОСТО СОЗДАТЬ массив 2^25? Ты уж определись - 2^25 или 2^27, т.к. разница очень существенная Добавлено PS: Единственная полезная инфа от выложенных картинок - это то, что свободный размер памяти у тебя превышает 2 Гб. Это говорит о том, что в твоей проге включен доступ к 3-му гигабайту (LARGE_ADDRESS_AWARE). Тем более не понятно, чем этот 3-й Гб занят, т.к. никакие dll обычно в него не грузятся ... |
Сообщ.
#21
,
|
|
|
2^26.
Прикреплённый файлDesktop.zip (37,91 Кбайт, скачиваний: 102) |
Сообщ.
#22
,
|
|
|
Цитата Сергей85 @ 2^26 Ну и ? В Project1 максимальный свободный блок памяти составляет 970 Мб, поэтому и "почему-то нет ошибки" при выделении 8*2^26 = 536 Мб. В vb6 максимальный блок равен 435 Мб (< 536 Мб), поэтому и происходит облом-с. Причина, как обычно, в дурных dll MS Office (в данном случае mso97rt.dll), которые норовят влезть по адресам вблизи 30000000H. Однако, хоть это и неприятно, но терпимо. Ты же уверяешь, что у тебя 2^24-2^25 не всегда выделяются, а это всего лишь 134-268 Мб - сколько еще нужно загрузить дурных dll, чтобы они так раздробили всё адресное пространство?! Можешь выложить пример, где с выделением 2^24-2^25 происходит облом? Насчет 3-го Гб я ошибся - макс.объем свободной памяти в Project1 не превышает 2Гб. Поэтому кардинальным решением проблемы в 64-битных ОС может быть разрешение для твоей программы использовать 3-й Гб (опция LARGE_ADRESS_AWARE). Это можно сделать с помощью утилиты editbin.exe, которая должна входить в состав VC6 (см. первый попавшийся пример). |
Сообщ.
#23
,
|
|
|
Option Explicit Option Compare Text Dim oExcelApp As New Excel.Application 'Приложение. Dim oDocExcel As New Excel.Workbook 'Документ Excel. Dim oExWs As New Excel.Worksheet 'Таблица документа Excel. Dim g_bCancel As Boolean 'Отмена ресурсоемкого процесса. Dim g_bCommand_Check_Click_Loaded As Boolean 'Самая ресурсоемкая функция завершила работу и успешно закрыла все приложения. Private Declare Function InitCommonControls Lib "Comctl32.dll" () As Long 'Для корректной загрузки COMCTL32.OCX в Windows XP. Private Declare Function GetDesktopWindow Lib "user32" () As Long Private Declare Function ShellExecute& Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long) 'Мгновенное копирование массивов. Private Sub Command_Check_Click() 1 On Error GoTo ErrorHandler 'Составление и заполнение массива данных. 3 Dim dNumbers_Array() As Double, dFormula_Array() As Double 'Открытие файла со списком номиналов. 20 g_oCommonDialog.FileName = "" 21 g_oCommonDialog.DialogTitle = "Открыть файл .XLS*" 22 g_oCommonDialog.Filter = "Файлы Microsoft Excel|*.xls*; *.csv" 23 If g_oCommonDialog.ShowOpen(Me) <> 0 Then Exit Sub 24 g_oCommonDialog.InitDir = g_oFSO.GetParentFolderName(g_oCommonDialog.FileName) 'Создать приложение Excel и скрытно работать с документом. 42 Set oExcelApp = New Excel.Application 43 oExcelApp.Visible = False 44 oExcelApp.IgnoreRemoteRequests = True 45 Set oDocExcel = oExcelApp.Workbooks.Open(g_oCommonDialog.FileName, , True) 46 Set oExWs = oDocExcel.ActiveSheet 'Работа построчно с передачей значений в функцию с формулами расчета. Количество комбинаций чисел - 2^n, что позволяет отказаться от факториалов и биномиального коэффициента. 47 While oExWs.Cells(lRow + 1, 1) <> "" 48 ReDim dNumbers_Array(0) 'Максимум чисел - 25. 49 dMaximum_Number = 0 50 iCol = 0 51 g_sTemp = "" 52 While oExWs.Cells(lRow + 1, iCol + 1) <> "" 53 If IsNumeric(oExWs.Cells(lRow + 1, iCol + 1)) Then 54 If iCol > 0 Then ReDim Preserve dNumbers_Array(iCol) 55 dNumbers_Array(iCol) = oExWs.Cells(lRow + 1, iCol + 1) 56 g_sTemp = g_sTemp & dNumbers_Array(iCol) & " " 57 If dMaximum_Number < dNumbers_Array(iCol) Then dMaximum_Number = dNumbers_Array(iCol) 58 Else 59 MsgBox "Ошибка: в строке " & lRow + 1 & " стоблце " & iCol & " указано не положительное число. Операция прервана, результаты на экране." 60 GoTo endd 61 End If 62 iCol = iCol + 1 63 Wend 64 [B]ReDim dFormula_Array(2 ^ (UBound(dNumbers_Array) + 1) - 2) 'Значение "все нули" не используется.[/B] Добавлено Не понимаю, как LARGE_ADRESS_AWARE подключается? По примеру фигня какая-то. Ведь получается, что проект должен вызвать editbin сам на себя. |
Сообщ.
#24
,
|
|
|
Используя небольшую хитрость на 64 битных системах можно выделить больше 4ГБ памяти.
|
Сообщ.
#25
,
|
|
|
Цитата TheTrik @ Иииии?.. |
Сообщ.
#26
,
|
|
|
Цитата Сергей85 @ Иииии?.. Учитывая что любой процесс в 64 битной среде является 64 битным, включая 32 битные то мы можем использовать все преимущества 64 битного режима из 32 битного процесса. Именно для выделения памяти нужно переключится в 64 битный режим, найти ntdll, найти функцию NtAllocateVirtualMemory, вызвать ее, получить указатель в 64 битном пространстве, переключится обратно. Писать/читать либо переключаясь в 64 битный режим либо с помощью функций NtWow64WriteVirtualMemory64/NtWow64ReadVirtualMemory64. |
Сообщ.
#27
,
|
|
|
Цитата Сергей85 @ Не понимаю, как LARGE_ADRESS_AWARE подключается? LARGE_ADRESS_AWARE подключается путем простой установки флага в заголовке exe-файла. В продвинутых компиляторах это делается путем задания соответствующей опции линкера. В vb6 такой возможности нет. Поэтому нужно использовать утилиту editbin.exe, которая установит нужный флаг в уже готовом\скомпилированном экзешнике. Для этого нужно в винде выполнить команду "путь\editbin.exe /largeaddressaware путь\имя_твоей_проги.exe". Чтобы каждый раз не набирать эту абру-кадабру, можно в папке с твоей программой создать либо bat-файл (простой текстовый файл с расширением bat) с соответствующей строкой, либо ярлык для editbin.exe, в котором через Свойства изменить строку Объект - добавить " /largeaddressaware имя_твоей_проги.exe". А чтобы не забыть про все это дело, можно в проге добавить вызов функции GlobalMemoryStatusEx (как рекомендовано в примере) с выдачей предупреждения в случае ullTotalVirtual <= 2 Гб. |
Сообщ.
#28
,
|
|
|
Замечания по коду #23.
1) Тебе уже в соседней ветке указали на то, что объявлять переменные oExcelApp, oDocExcel и oExWs через New не нужно, т.к. во-первых, это не имеет смысла, поскольку в Command_Check_Click ты их все равно устанавливаешь заново, во-вторых, создание Excel.Workbook и Worksheet через New может приводить к той самой ошибке 429 - "ActiveX component can't create object". 2) Я уже говорил, что вызов диалога открытия файла подгружает кучу разных dll (в том числе и совершенно левых, отвечающих за опции контекстного меню файла) и создает несколько потоков - все это может негативно сказываться на фрагментации адресного пространства твоей проги. Работа с объектами Excel также может приводить к подгрузке офисных dll, созданию расшареных регионов памяти и т.п. Поэтому, раз у тебя максимальный размер массива dFormula_Array не может превышать 2^25*8 = 268 Мб (по сути - это "мелочь пузатая"), то лучше выделить память под него сразу при старте проги (до вызова диалога открытия файла и создания объектов Excel - например, в Form_Load). Если в Command_Check_Click окажется, что для массива нужно меньше памяти, то можно сделать ReDim для уменьшения его размера (только без Preserve - иначе м.б. облом!) PS: Наращивать длину массива dNumbers_Array по одному элементу, когда их максимальное число не может превышать 25 - это как-то э-э-э, "не профессионально". Проще использовать статический массив (можно с запасом, например на 32 элемента), а реальное кол-во используемых элементов хранить в отдельной переменной типа dNumbers_Count As integer |
Сообщ.
#29
,
|
|
|
1) Пробовал с разными вариантами перетасовки New - ошибка не меняется.
2) Ясно. PS: что быстрее: Ubound(Array) или int при указании в условиях цикла For? Мне скорость циклов важнее, чем скорость заполнения массива dNumbers. |
Сообщ.
#30
,
|
|
|
Цитата Сергей85 @ что быстрее: Ubound(Array) или int при указании в условиях цикла For? Теоретически int "быстрее", но практически в цикле For ты разницы не заметишь, т.к. при For верхний предел (по идее) должен вычисляться только один раз перед входом в цикл (а не на каждой итерации как в while и do..loop) |