Shared memory

http://www.codeproject.com/KB/threads/sm.aspx

等有时间了过来翻译一下。

Motivation

Sometimes you need to share some values across several processes. There are some ways, provided by system, but there is no simple way to share simple values like DWORDs or strings. And of course, synchronization is also required in this case.

Description of solution

I was inspired by PJ Naughter's solution, but I wanted more. I wanted structured shared memory, with variables, synchronization and wait functionality within it.

Internal structure

Variables are shared within an unnamed memory file. This 'file' (or better, block of memory) is allocated in the page file. It is not possible to create growable file of this type, but I did not require it. The internal structure of this memory is as follows:

Collapse Copy Code
DWORD
DWORD 
ValueHeader[0]
value 0 
ValueHeader[1]
value 1 
..............
ValueHeader[n]
value n

The first DWORD is the number of values within memory. The second DWORD is the memory size; it includes these two DWORDs too. ValueHeader is a structure defined as:

Collapse Copy Code
typedef struct _tagValueHeader {
	WCHAR wszValueName[VAR_NAME_LENGTH];
	DWORD dwLength; 
} ValueHeader;

Member wszValueName is value name, dwLength is length in bytes of the value, which follows this structure. As you can see, the actual value is stored as several bytes. There is no type checking of the value's type. It is not allowed access the variable directly. Instead of that, the class provides several methods to access values. It allows synchronized access, and it is possible to wait for value or memory changes.

CSharedMemory public class members

Construction and destructions
CSharedMemory
~CSharedMemory

General methods
GetMemName
IsCreated
GetMemSize
AmIFirst
GetLastError

Access control methods
SetSdMem
GetSdMem
SetSdSem
GetSdSem
SetSaEvent

Value management methods
AddValue
AddDwordValue
DeleteValue
ExistValue
GetVariablesCount
GetValueInfo

Value access methods
SetValue
GetValue

Wait methods
WaitForMemChange
WaitForValueChange
WaitForMultipleValuesChanges

Interlocked* methods
InterlockedIncrement
InterlockedDecrement
InterlockedExchange
InterlockedTestExchange
InterlockedCompareExchange
InterlockedExchangeAdd

Direct memory access methods
Read
Write

DEBUG methods
AssertValid
Dump

CSharedMemory::CSharedMemory

CSharedMemory(TCHAR *szName, DWORD dwSize = DEF_SHARED_SIZE, PINITMEMORY InitMemoryProcedure = NULL, void *pInitProcParam = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL);

Remarks

Constructor for the class. It creates shared memory named szName, of dwSize< size. When you want initialize memory at the same place as you declare it, you can define an initializer function, defined as:

Collapse Copy Code
void InitMemory(CSharedMemory *pMem, void *pInitProcParam)

And you can pass its address to the constructor. This solution allows you write shorter code like:

Collapse Copy Code
...
CSharedMemory sh_mem("MemoryName",1024,InitMemory);
...

'Initialize' means, for example to add some variables. If you need to pass your own initialization value, then you can specify it in the pInitProcParam parameter. If you don't provide this value at the construction time, then constructor will pass NULL to your initializer function. lpsaAttributes defines access control rights and security attributes of the memory mapped file, semaphore and events created inside the CSharedMemory object. For more information see SECURITY_ATTRIBUTES.

CSharedMemory::~CSharedMemory

~CSharedMemory();

Remarks

Destructor for the class. It frees all allocated resources.

CSharedMemory::GetMemName

CString GetMemName(void);

Remarks

Returns name of the shared memory.

CSharedMemory::IsCreated

BOOL IsCreated(void);

Remarks

Returns TRUE if memory was successfully created.

CSharedMemory::GetMemSize

DWORD GetMemSize(void);

Remarks

Returns size of memory.

CSharedMemory::AmIFirst

BOOL AmIFirst(void);

Remarks

Returns TRUE, if caller was first, who created memory.

CSharedMemory::GetLastError

DWORD GetLastError(void);

Remarks

Returns a Win32 error code that describes the best last error inside a call made to the object.

CSharedMemory::SetSdMem

BOOL SetSdMem(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor);

Remarks

This method sets the security descriptor for memory mapped file. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve error code. See also SetKernelObjectSecurity().

CSharedMemory::GetSdMem

BOOL GetSdMem(SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded);

Remarks

This method gets the security descriptor of the memory mapped file. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve error code. See also GetKernelObjectSecurity().

CSharedMemory::SetSdSem

BOOL SetSdSem(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor);

Remarks

This method sets the security descriptor of the semaphore, which synchronizes access to shared memory. If it fails, returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code. See also SetKernelObjectSecurity().

CSharedMemory::GetSdSem

BOOL GetSdSem(SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded);

Remarks

This method gets security descriptor of the semaphore, which synchronizes access to shared memory. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code. See also GetKernelObjectSecurity().

CSharedMemory::SetSaEvent

CSharedMemory::GetLastError() to retrieve error code.

BOOL SetSaEvent(LPSECURITY_ATTRIBUTES lpsaAttributes);

Remarks:

This method sets internal variable to security attributes, which are used to protect internal events object. These events are used to 'wait' for changes in the memory or variable. If it fails, it returns FALSE, otherwise TRUE. Call

CSharedMemory::AddValue

BOOL AddValue(const TCHAR *szName, DWORD size, void *pDefaultData = NULL);

Remarks

This method adds new value named szName. It creates a new entry within memory and reserves space of size for new value. If it fails, returns FALSE, otherwise TRUE. You can use the last parameter to set its value after it is created. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::AddDwordValue

BOOL AddDwordValue(const TCHAR *szName, DWORD dwDefault = 0);

Remarks

Method adds new DWORD value named szName. It creates a new entry within memory and reserves space of size for new value. If it fails, it returns FALSE, otherwise TRUE. You can use last parameter to set its value after it is created. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::DeleteValue

BOOL DeleteValue(TCHAR *szName);

Remarks

This method deletes the value named szName from memory, it frees used space and freed memory is filled with zeros. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve error code.

CSharedMemory::ExistValue

BOOL ExistValue(TCHAR *szName);

Remarks

This method returns TRUE, if variable szName exists within memory. If it fails, returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code (when constructor failed, this method returns FALSE, but CSharedMemory::GetLastError() returns a different error code).

CSharedMemory::GetVariablesCount

DWORD GetVariablesCount(void);

Remarks

This method returns the number of values stored in the memory. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::GetValueInfo

BOOL GetValueInfo(DWORD dwIndex, ValueHeader *pVarInfo);

Remarks

This method copies value information of the format ValueHeader to memory pointed by pVarInfo. If it fails, returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::SetValue

BOOL SetValue(TCHAR *szName, void *bData, DWORD dwLength);

Remarks

This method sets the variable named szName to value pointed to by bData. Length of the data at address bData is passed as the last parameter. It can be less then allocated length within shared memory. In this case the rest of the allocated buffer is filled with zeros. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::GetValue

BOOL GetValue(TCHAR *szName, void *bData, LPDWORD dwLength);

Remarks

This method retrieves thevalue of the variable szName. Data is stored at address bData. The length stored at bData is returned in dwLength. It is possible to pass in bData NULL, then the method returns in dwLength the required buffer length. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError()to retrieve the error code.

CSharedMemory::WaitForMemChange

DWORD WaitForMemChange(DWORD dwMilliseconds = INFINITE);

Remarks

This method waits for any change in the structure of the shared memory. 'Change' means add or delete a variable. When you do not use variables, but direct access functions, then you can use this method to wait for the changes. For direct access see CSharedMemory::Read() or CSharedMemory::Write(). If it fails, it returns WAIT_FAILED value, see also WaitForSingleObject() .

CSharedMemory::WaitForValueChange

DWORD WaitForValueChange(TCHAR *szName, DWORD dwMilliseconds = INFINITE);

Remarks

This methods waits for changes of value. It also returns, when a variable is deleted. If it fails, itreturns WAIT_FAILED value, see also WaitForSingleObject().

CSharedMemory::WaitForMultipleValuesChanges

DWORD CSharedMemory::WaitForMultipleValuesChanges(CStringArray & str,BOOL bWaitForAll , DWORD dwMilliseconds =INFINITE );

Remarks

This methods waits for changes of values. It also returns when variables are deleted. You can choose to wait for change of one or several values. If it fails, it returns WAIT_FAILED value, see also WaitForMultipleObject().

All Interlocked* functions are described in the MSDN. Methods of CSharedMemory work the same way, except they return TRUE/FALSE as an indicator of success, and the return value of emulated functions is returned through a pointer (usually the last optional parameter).

CSharedMemory::InterlockedIncrement

BOOL InterlockedIncrement(TCHAR *szName, LPLONG plNewVal = NULL);

Remarks

See also InterlockedIncrement().

CSharedMemory::InterlockedDecrement

BOOL InterlockedDecrement(TCHAR *szName, LPLONG plNewVal = NULL);

Remarks

See also InterlockedDecrement().

CSharedMemory::InterlockedExchange

BOOL InterlockedExchange(TCHAR *szTargetName, LONG lNewVal, LPLONG plPrevValue = NULL);

Remarks

See also InterlockedExchange().

CSharedMemory::InterlockedTestExchange

BOOL InterlockedTestExchange(TCHAR *szTargetName, LONG lOldValue, LONG lNewValue, LPLONG plPrevValue = NULL);

Remarks

See also InterlockedTestExchange().

CSharedMemory::InterlockedCompareExchange

BOOL InterlockedCompareExchange(TCHAR *szTargetName, LONG lExchange, LONG lComperand, LPLONG plIntiVal = NULL);

Remarks

See also InterlockedCompareExchange().

CSharedMemory::InterlockedExchangeAdd

BOOL InterlockedExchangeAdd(TCHAR *szTargetName, LONG lIncrement, LPLONG plIntiVal = NULL);

Remarks

See also InterlockedExchangeAdd().

CSharedMemory::Read

BOOL Read(BYTE *pbData, DWORD dwLength, DWORD dwOffset = 0);

Remarks

This method reads dwLength bytes from offset dwOffset within memory. It is allowed to access shared memory this way only when it contains no variables. Method writes data at the address pbData. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::Write

BOOL Write(BYTE *pbData, DWORD dwLength, DWORD dwOffset = 0);

Remarks

Method writes dwLength bytes from pbData at the offset dwOffeset within the shared memory. It is allowed to access shared memory this way only when it contains no variables. If it fails, it returns FALSE, otherwise TRUE. Call CSharedMemory::GetLastError() to retrieve the error code.

CSharedMemory::AssertValid

void AssertValid(void);

Remarks

This methof performs a validity check on this object by checking its internal state.

CSharedMemory::Dump

void Dump(CDumpContext & dc);

Remarks

Dumps the contents of shared memory to a CDumpContext object.

Usage

I have provided a simple demo program to demonstrate usage of the CSharedMemory class. A shared block of the memory exists within the system until the last instance of the CSharedMemory class is destroyed. CSharedMemory is UNICODE enabled; it will work in UNICODE or ANSI programs. It is possible to share the same memory from both types of programs. CSharedMemory uses simple diagnostic functions from Helpers.h and Helpers.cpp

Demo program

 

The demo program provides an interface to the many methods of CSharedMemory, and you can use more instances of it to play with CSharedMemory and see how it works. It also demonstrates usage of the class.

History

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: CUDA共享内存是一种特殊的内存类型,它可以在同一个线程块内的线程之间共享数据。这种内存类型的访问速度非常快,因为它是在GPU芯片上的SRAM中实现的。使用共享内存可以有效地减少全局内存的访问,从而提高CUDA程序的性能。共享内存的大小是有限制的,通常为每个线程块的总共享内存大小的一半。因此,在使用共享内存时需要仔细考虑内存的使用情况,以避免内存溢出和性能下降。 ### 回答2: CUDA shared memory是一种专门用于加速GPU并行计算的高速缓存区域。它位于GPU的多个处理核心之间共享,并在同一个线程块中的线程之间交流数据。相比于全局内存,shared memory具有更低的访问延迟和更高的带宽。 shared memory可以通过声明__shared__关键字来定义,并通过静态分配的方式进行初始化。每个线程块都具有自己独立的shared memory空间,其大小在编译时确定,但最大限制为48KB。 shared memory的主要优点是其高带宽和低延迟。由于其位于多个处理核心之间共享,可以实现线程之间的快速数据交换。通过将计算中频繁使用的数据存储在shared memory中,可以减少从全局内存中读取数据所需的时间。这对于那些具有访存限制的算法,如矩阵乘法和图像处理等,非常有用。 使用shared memory还可以避免线程间的数据冗余读取,从而提高整体的并行计算效率。当多个线程需要访问相同的数据时,可以将这些数据存储在shared memory中,以便线程之间进行共享,从而减少了重复的全局内存访问。 但shared memory也有一些限制和需要注意的地方。首先,shared memory的大小是有限的,需要根据具体的算法和硬件限制进行适当调整。其次,由于其共享的特性,需要确保线程之间的数据同步。最后,使用shared memory时需要注意避免bank conflict,即多个线程同时访问同一个shared memory bank造成的资源竞争,从而导致性能下降。 综上所述,CUDA shared memory在GPU并行计算中具有重要的作用。通过使用shared memory,可以有效减少全局内存访问、提高数据交换速度和并行计算效率,从而加速GPU上的并行计算任务。 ### 回答3: CUDA共享内存(shared memory)是指在CUDA程序中使用的一种特殊的内存空间。它是GPU上的一块高速、低延迟的内存,被用来在同一个线程块(thread block)中的线程之间进行数据共享。 与全局内存相比,共享内存的访问速度更快,读写延迟更低。这是因为共享内存位于SM(Streaming Multiprocessor)内部,可以直接被SM访问,而全局内存则需要通过PCIe总线与主机内存进行通信。 使用共享内存可以提高应用程序性能的原因之一是避免了全局内存的频繁访问。当多个线程需要读写同一个数据时,如果每个线程都从全局内存中读取/写入,会导致内存带宽饱和,限制了整体性能。而将这些数据缓存在共享内存中,可以减少对全局内存的访问次数,提高内存带宽的利用率。 除此之外,共享内存的另一个重要特性是可以用作线程间的通信机制。在同一个线程块中的线程可以通过共享内存交换数据,而无需利用全局内存作为中介。这使得线程之间的协作变得更加高效和灵活。 然而,共享内存也有一些限制。首先,共享内存的大小是有限的,通常为每个SM的一定容量(如16KB或48KB)。其次,共享内存的生命周期与线程块相同,每个线程块结束后,共享内存中的数据将被销毁。 在编写CUDA程序时,可以使用__shared__关键字来声明共享内存。同时需要注意,合理地使用共享内存,并避免冲突和竞争条件,才能充分发挥共享内存的优势,提高CUDA程序的性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值