OMP:如何在运行时找到合适大小的缓存
OMP: How to find the right size of cache at runtime
我有以下一段(伪)代码:
static void ConvertBuffer( unsigned char * buffer, const int width )
{
#pragma omp parallel for
for ( int x = 0; x < width; ++x ) // one image row
{
RGB rgb = {0,0,0}; HSB hsb;
rgb.red = (float)buffer[x] / 255.;
RGBToHSB(rgb, hsb);
buffer[x] = hsb.brightness * 255;
}
}
这是一个非常简单的 RGB → HSB 转换算法实现。
第一个实现将一次拉出一条扫描线(=图像的一行),在我的例子中 65536 字节。然而,在我的特定系统上反复试验后,我发现我可以将总计算时间减少 2 倍,如果我处理 16[=30] =] 一次扫描线(= 1048576 字节)。
有什么工具可以让我猜测 幻数,可能在运行时,这样我就不需要在代码中的某处硬编码一个幻数 16 了?
如果我知道 RGBToHSB
是令人尴尬的并行和缓存友好,我可以完全填充 L3 cache
并且应该接近最大可能速度吗?
作为参考,我的系统描述如下:
$ sudo likwid-topology
-------------------------------------------------------------
CPU type: Intel Core SandyBridge processor
*************************************************************
Hardware Thread Topology
*************************************************************
Sockets: 1
Cores per socket: 4
Threads per core: 1
-------------------------------------------------------------
HWThread Thread Core Socket
0 0 0 0
1 0 1 0
2 0 2 0
3 0 3 0
-------------------------------------------------------------
Socket 0: ( 0 1 2 3 )
-------------------------------------------------------------
*************************************************************
Cache Topology
*************************************************************
Level: 1
Size: 32 kB
Cache groups: ( 0 ) ( 1 ) ( 2 ) ( 3 )
-------------------------------------------------------------
Level: 2
Size: 256 kB
Cache groups: ( 0 ) ( 1 ) ( 2 ) ( 3 )
-------------------------------------------------------------
Level: 3
Size: 6 MB
Cache groups: ( 0 1 2 3 )
-------------------------------------------------------------
*************************************************************
NUMA Topology
*************************************************************
NUMA domains: 1
-------------------------------------------------------------
Domain 0:
Processors: 0 1 2 3
Relative distance to nodes: 10
Memory: 122.332 MB free of total 5898.17 MB
-------------------------------------------------------------
您不能真正定义 'right size' 用于缓冲。我的答案是将它设置得尽可能大。我会说介于 10MB 和 100MB 之间,但如果您负担得起,可以将其设置得更高,如果 RAM 不足,则可以将其设置得更低。
如果你正在读取一个文件并写入一个文件(相同或另一个),你应该考虑使用内存映射文件。这样你就摆脱了缓冲(由 OS 管理),你可以为整个图像调用一次你的函数。请注意,如果您的图像大于 4GB,这在 32 位系统上可能不是一个好主意。
我有以下一段(伪)代码:
static void ConvertBuffer( unsigned char * buffer, const int width )
{
#pragma omp parallel for
for ( int x = 0; x < width; ++x ) // one image row
{
RGB rgb = {0,0,0}; HSB hsb;
rgb.red = (float)buffer[x] / 255.;
RGBToHSB(rgb, hsb);
buffer[x] = hsb.brightness * 255;
}
}
这是一个非常简单的 RGB → HSB 转换算法实现。
第一个实现将一次拉出一条扫描线(=图像的一行),在我的例子中 65536 字节。然而,在我的特定系统上反复试验后,我发现我可以将总计算时间减少 2 倍,如果我处理 16[=30] =] 一次扫描线(= 1048576 字节)。
有什么工具可以让我猜测 幻数,可能在运行时,这样我就不需要在代码中的某处硬编码一个幻数 16 了?
如果我知道 RGBToHSB
是令人尴尬的并行和缓存友好,我可以完全填充 L3 cache
并且应该接近最大可能速度吗?
作为参考,我的系统描述如下:
$ sudo likwid-topology
-------------------------------------------------------------
CPU type: Intel Core SandyBridge processor
*************************************************************
Hardware Thread Topology
*************************************************************
Sockets: 1
Cores per socket: 4
Threads per core: 1
-------------------------------------------------------------
HWThread Thread Core Socket
0 0 0 0
1 0 1 0
2 0 2 0
3 0 3 0
-------------------------------------------------------------
Socket 0: ( 0 1 2 3 )
-------------------------------------------------------------
*************************************************************
Cache Topology
*************************************************************
Level: 1
Size: 32 kB
Cache groups: ( 0 ) ( 1 ) ( 2 ) ( 3 )
-------------------------------------------------------------
Level: 2
Size: 256 kB
Cache groups: ( 0 ) ( 1 ) ( 2 ) ( 3 )
-------------------------------------------------------------
Level: 3
Size: 6 MB
Cache groups: ( 0 1 2 3 )
-------------------------------------------------------------
*************************************************************
NUMA Topology
*************************************************************
NUMA domains: 1
-------------------------------------------------------------
Domain 0:
Processors: 0 1 2 3
Relative distance to nodes: 10
Memory: 122.332 MB free of total 5898.17 MB
-------------------------------------------------------------
您不能真正定义 'right size' 用于缓冲。我的答案是将它设置得尽可能大。我会说介于 10MB 和 100MB 之间,但如果您负担得起,可以将其设置得更高,如果 RAM 不足,则可以将其设置得更低。
如果你正在读取一个文件并写入一个文件(相同或另一个),你应该考虑使用内存映射文件。这样你就摆脱了缓冲(由 OS 管理),你可以为整个图像调用一次你的函数。请注意,如果您的图像大于 4GB,这在 32 位系统上可能不是一个好主意。