Я пытаюсь создать распределенную вычислительную систему, которая использует файлы сопоставления памяти для координации работы между несколькими сетевыми ПК через VBA. Иными словами, я хочу, чтобы группа компьютеров, объединенных в сеть, одновременно и скоординировано работали над одним проектом, который можно было бы легко разделить на разные части. Для завершения проекта на одном компьютере требуется более 13 часов, что нецелесообразно для моего клиента.
Я хочу хранить информацию в файлах сопоставления памяти, которые помогут ПК работать над проектом скоординированно (т. е. без дублирования работы, избегая проблем с гонками и т. д.). Я пытался использовать другие типы файлов для достижения этой цели, но это вызывало проблемы с гонкой за файлами или занимало слишком много времени. Итак, как было предложено на этом форуме, я пытаюсь использовать файлы отображения памяти.
Я новичок в файлах отображения памяти и распределенных вычислениях. Должен быть сделан в VBA. Насколько я знаю, я должен указать, что файл должен быть сохранен в каталоге в нашей сети (здесь диск Z), к которому имеют доступ все ПК. Я собрал код из разных мест:
Option Explicit
Private Const PAGE_READWRITE As Long = &H4
Private Const FILE_MAP_WRITE As Long = &H2
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_ALWAYS = 4
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CreateFileMapping Lib "kernel32.dll" Alias "CreateFileMappingA" ( _
ByVal hFile As Long, _
ByVal lpFileMappigAttributes As Long, _
ByVal flProtect As Long, _
ByVal dwMaximumSizeHigh As Long, _
ByVal dwMaximumSizeLow As Long, _
ByVal lpName As String) As Long
Private Declare Function MapViewOfFile Lib "kernel32.dll" ( _
ByVal hFileMappingObject As Long, _
ByVal dwDesiredAccess As Long, _
ByVal dwFileOffsetHigh As Long, _
ByVal dwFileOffsetLow As Long, _
ByVal dwNumberOfBytesToMap As Long) As Long
#If VBA7 Then
Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (destination As Any, source As Any, _
ByVal length As Long)
#Else
Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (destination As Any, source As Any, _
ByVal length As Long)
#End If
Private Declare Function UnmapViewOfFile Lib "kernel32.dll" ( _
ByRef lpBaseAddress As Any) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" ( _
ByVal hObject As Long) As Long
Private hMMF As Long
Private pMemFile As Long
Sub IntoMemoryFileOutOfMemoryFile()
Dim sFile As String
Dim hFile As Long
sFile = "Z:\path\test1.txt"
hFile = CreateFile(sFile, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
hMMF = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 1000000, "MyMemoryMappedFile")
pMemFile = MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 0)
Dim buffer As String
buffer = "testing1"
CopyMemory pMemFile, ByVal buffer, 128
hMMF = CreateFileMapping(-1, 0, PAGE_READWRITE, 0, 1000000, "MyMemoryMappedFile")
pMemFile = MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 0)
Dim buffer2 As String
buffer2 = String$(128, vbNullChar)
CopyMemory ByVal buffer2, pMemFile, 128
MsgBox buffer2 & " < - it worked?"
UnmapViewOfFile pMemFile
CloseHandle hMMF
End Sub
В качестве небольшого примера приведенный выше код пытается поместить строку «testing1» в файл test1.txt, затем извлечь эту строку и сохранить ее в переменной buffer2 и, наконец, отобразить эту строку через окно msgbox. Супер просто. Однако я понятия не имею, что делаю.
Все наши ПК 64-битные, Windows 7, Office/Excel 2013.
Проблемы/вопросы:
- msgbox пуст, когда я запускаю IntoMemoryFileOutOfMemoryFile
- После завершения подпрограммы я открываю test1.txt и получаю: «Процесс не может получить доступ к файлу, поскольку он используется другим процессом». Что говорит мне, что я неправильно использую UnmapViewOfFile и/или CloseHandle.
- Я хотел бы сделать эти файлы памяти постоянными, чтобы, если все компьютеры будут прерваны, я мог перезапустить процесс и продолжить с того места, где остановился.
Вот некоторые из ссылок, которые я использовал, чтобы добраться туда, где я сейчас:
https://msdn.microsoft.com/en-us/library/dd997372%28v=vs.110%29.aspx
http://vb.mvps.org/hardcore/html/sharedmemorythroughmemory-mappedfiles.htm
http://www.tushar-mehta.com/publish_train/xl_vba_cases/1016%20Office%202010%20VBA.shtml
Интересная, но неважная информация: «Проект» предназначен для клиента хедж-фонда. Я финансист, перешедший на фундаментальные количественные расчеты. Мы ежедневно анализируем более 2000 акций в более чем 1250 полях данных, чтобы делать макроэкономические сигналы/прогнозы для покупки и продажи акций, фьючерсов и опционов.
ОБНОВЛЕНИЕ: Если я изменю две строки CopyMemory следующим образом (передаю pMemFile по значению) соответственно:
CopyMemory ByVal pMemFile, buffer, 128
а также...
CopyMemory buffer2, ByVal pMemFile, 128
Я получаю кучу сумасшедших символов в файле test1.txt и происходит сбой excel.