获取Fortran程序内存使用情况的方法
文章目录
- 获取Fortran程序内存使用情况的方法
- Linux系统下的方法
- 1. 使用`getrusage`系统调用
- 2. 读取/proc/self/statm文件
- Windows系统下的方法
- 1. 使用Windows API GetProcessMemoryInfo
- 跨平台解决方案
- 注意事项
获取Fortran程序内存使用情况的方法
在Fortran程序中获取当前进程的内存使用情况,可以通过以下几种方法实现,分别适用于Linux和Windows系统。
Linux系统下的方法
1. 使用getrusage
系统调用
program memory_usageimplicit noneinteger, parameter :: RUSAGE_SELF = 0integer :: ierrinteger(kind=8) :: maxrssinterfacesubroutine getrusage(who, usage) bind(C, name="getrusage")use iso_c_bindinginteger(c_int), value :: whotype :: timevalinteger(c_long) :: tv_sec, tv_usecend typetype :: rusagetype(timeval) :: ru_utime, ru_stimeinteger(c_long) :: ru_maxrss, ru_ixrssinteger(c_long) :: ru_idrss, ru_isrssinteger(c_long) :: ru_minflt, ru_majfltinteger(c_long) :: ru_nswap, ru_inblockinteger(c_long) :: ru_oublock, ru_msgsndinteger(c_long) :: ru_msgrcv, ru_nsignalsinteger(c_long) :: ru_nvcsw, ru_nivcswend typetype(rusage) :: usageend subroutineend interfacetype :: rusageinteger(8) :: ru_utime_sec, ru_utime_usecinteger(8) :: ru_stime_sec, ru_stime_usecinteger(8) :: ru_maxrss, ru_ixrssinteger(8) :: ru_idrss, ru_isrssinteger(8) :: ru_minflt, ru_majfltinteger(8) :: ru_nswap, ru_inblockinteger(8) :: ru_oublock, ru_msgsndinteger(8) :: ru_msgrcv, ru_nsignalsinteger(8) :: ru_nvcsw, ru_nivcswend typetype(rusage) :: usagecall getrusage(RUSAGE_SELF, usage)print *, "Maximum resident set size (KB):", usage%ru_maxrss
end program
2. 读取/proc/self/statm文件
program read_proc_statmimplicit noneinteger :: unit, ierrinteger(kind=8) :: size, resident, share, text, lib, data, dtcharacter(len=256) :: lineopen(newunit=unit, file="/proc/self/statm", action="read", iostat=ierr)if (ierr /= 0) thenprint *, "Error opening /proc/self/statm"stopend ifread(unit, *, iostat=ierr) size, resident, share, text, lib, data, dtclose(unit)if (ierr /= 0) thenprint *, "Error reading /proc/self/statm"stopend if! 页面大小通常为4KBprint *, "Virtual memory size (pages):", sizeprint *, "Resident set size (pages):", residentprint *, "Shared pages:", shareprint *, "Text (code) pages:", textprint *, "Library pages:", libprint *, "Data/stack pages:", dataprint *, "Dirty pages:", dt! 转换为KBprint *, "Resident set size (KB):", resident * 4
end program
Windows系统下的方法
1. 使用Windows API GetProcessMemoryInfo
program windows_memory_usageuse, intrinsic :: iso_c_bindingimplicit none! 定义Windows API接口interfacefunction GetCurrentProcess() bind(C, name="GetCurrentProcess")use iso_c_bindingtype(c_ptr) :: GetCurrentProcessend functionfunction GetProcessMemoryInfo(hProcess, ppsmemCounters, cb) bind(C, name="GetProcessMemoryInfo")use iso_c_bindinginteger(c_int) :: GetProcessMemoryInfotype(c_ptr), value :: hProcesstype(c_ptr), value :: ppsmemCountersinteger(c_int), value :: cbend functionend interface! 定义PROCESS_MEMORY_COUNTERS结构体type, bind(C) :: PROCESS_MEMORY_COUNTERSinteger(c_int) :: cbinteger(c_int) :: PageFaultCountinteger(c_size_t) :: PeakWorkingSetSizeinteger(c_size_t) :: WorkingSetSizeinteger(c_size_t) :: QuotaPeakPagedPoolUsageinteger(c_size_t) :: QuotaPagedPoolUsageinteger(c_size_t) :: QuotaPeakNonPagedPoolUsageinteger(c_size_t) :: QuotaNonPagedPoolUsageinteger(c_size_t) :: PagefileUsageinteger(c_size_t) :: PeakPagefileUsageend typetype(PROCESS_MEMORY_COUNTERS) :: pmcinteger(c_int) :: successtype(c_ptr) :: hProcess! 初始化结构体大小pmc%cb = sizeof(pmc)! 获取当前进程句柄hProcess = GetCurrentProcess()! 获取内存信息success = GetProcessMemoryInfo(hProcess, c_loc(pmc), pmc%cb)if (success == 0) thenprint *, "Failed to get process memory info"elseprint *, "Working Set Size (KB):", pmc%WorkingSetSize / 1024print *, "Peak Working Set Size (KB):", pmc%PeakWorkingSetSize / 1024print *, "Pagefile Usage (KB):", pmc%PagefileUsage / 1024end if
end program
跨平台解决方案
为了编写跨平台的代码,可以使用预处理指令来区分不同操作系统:
program cross_platform_memoryuse, intrinsic :: iso_c_bindingimplicit none! 定义操作系统相关的预处理指令
#ifdef __linux__print *, "Linux memory usage:"call linux_memory_usage()
#elif _WIN32print *, "Windows memory usage:"call windows_memory_usage()
#elseprint *, "Unsupported operating system"
#endifcontains#ifdef __linux__subroutine linux_memory_usage()integer :: unit, ierrinteger(kind=8) :: residentcharacter(len=256) :: lineopen(newunit=unit, file="/proc/self/statm", action="read", iostat=ierr)if (ierr /= 0) thenprint *, "Error opening /proc/self/statm"returnend ifread(unit, *, iostat=ierr) line ! 只需要第一个值close(unit)if (ierr /= 0) thenprint *, "Error reading /proc/self/statm"returnend if! 简单示例,实际应解析line获取resident值print *, "Resident set size (approximate, KB): (parse /proc/self/statm for actual value)"end subroutine
#endif#ifdef _WIN32subroutine windows_memory_usage()interfacefunction GetCurrentProcess() bind(C, name="GetCurrentProcess")use iso_c_bindingtype(c_ptr) :: GetCurrentProcessend functionfunction GetProcessMemoryInfo(hProcess, ppsmemCounters, cb) bind(C, name="GetProcessMemoryInfo")use iso_c_bindinginteger(c_int) :: GetProcessMemoryInfotype(c_ptr), value :: hProcesstype(c_ptr), value :: ppsmemCountersinteger(c_int), value :: cbend functionend interfacetype :: PROCESS_MEMORY_COUNTERSinteger(c_int) :: cbinteger(c_int) :: PageFaultCountinteger(c_size_t) :: PeakWorkingSetSizeinteger(c_size_t) :: WorkingSetSizeinteger(c_size_t) :: QuotaPeakPagedPoolUsageinteger(c_size_t) :: QuotaPagedPoolUsageinteger(c_size_t) :: QuotaPeakNonPagedPoolUsageinteger(c_size_t) :: QuotaNonPagedPoolUsageinteger(c_size_t) :: PagefileUsageinteger(c_size_t) :: PeakPagefileUsageend typetype(PROCESS_MEMORY_COUNTERS) :: pmcinteger(c_int) :: successtype(c_ptr) :: hProcesspmc%cb = sizeof(pmc)hProcess = GetCurrentProcess()success = GetProcessMemoryInfo(hProcess, loc(pmc), pmc%cb)if (success == 0) thenprint *, "Failed to get process memory info"elseprint *, "Working Set Size (KB):", pmc%WorkingSetSize / 1024end ifend subroutine
#endifend program
注意事项
- 在Linux上,
/proc/self/statm
提供的是以页面为单位的内存使用情况,通常页面大小为4KB。 - Windows API返回的值是以字节为单位的,需要除以1024转换为KB。
- 跨平台代码需要使用适当的编译器预处理指令来区分不同平台。
- 对于更复杂的需求,可能需要编写更多的C接口代码或使用第三方库。
以上方法可以帮助你在Fortran程序中获取当前进程的内存使用情况。