- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想在 RAM 上分配大约 40 GB。我的第一次尝试是:
#include <iostream>
#include <ctime>
int main(int argc, char** argv)
{
unsigned long long ARRAYSIZE = 20ULL * 1024ULL * 1024ULL * 1024ULL;
unsigned __int16 *myBuff = new unsigned __int16[ARRAYSIZE]; // 3GB/s 40GB / 13.7 s
unsigned long long i = 0;
const clock_t begintime = clock();
for (i = 0; i < ARRAYSIZE; ++i){
myBuff[i] = 0;
}
std::cout << "finish: " << float(clock() - begintime) / CLOCKS_PER_SEC << std::endl;
std::cin.get();
delete [] myBuff;
return 0;
}
内存写入速度约为 3 GB/s,这对我的高性能系统来说并不令人满意。
所以我尝试了英特尔 Cilk Plus,如下所示:
/*
nworkers = 5; 8.5 s ==> 4.7 GB/s
nworkers = 8; 8.2 s ==> 4.8 GB/s
nworkers = 10; 9 s ==> 4.5 GB/s
nworkers = 32; 15 s ==> 2.6 GB/s
*/
#include "cilk\cilk.h"
#include "cilk\cilk_api.h"
#include <iostream>
#include <ctime>
int main(int argc, char** argv)
{
unsigned long long ARRAYSIZE = 20ULL * 1024ULL * 1024ULL * 1024ULL;
unsigned __int16 *myBuff = new unsigned __int16[ARRAYSIZE];
if (0 != __cilkrts_set_param("nworkers", "32")){
std::cout << "Error" << std::endl;
}
const clock_t begintime = clock();
cilk_for(long long j = 0; j < ARRAYSIZE; ++j){
myBuff[j] = 0;
}
std::cout << "finish: " << float(clock() - begintime) / CLOCKS_PER_SEC << std::endl;
std::cin.get();
delete [] myBuff;
return 0;
}
结果注释在代码上方。可以看出,当 nworkers = 8 时速度会加快。但是 nworkers 越大,分配越慢。我想可能是由于线程锁定。所以我尝试了英特尔 TBB 提供的可扩展分配器:
#include "tbb\task_scheduler_init.h"
#include "tbb\blocked_range.h"
#include "tbb\parallel_for.h"
#include "tbb\scalable_allocator.h"
#include "cilk\cilk.h"
#include "cilk\cilk_api.h"
#include <iostream>
#include <ctime>
// No retry loop because we assume that scalable_malloc does
// all it takes to allocate the memory, so calling it repeatedly
// will not improve the situation at all
//
// No use of std::new_handler because it cannot be done in portable
// and thread-safe way (see sidebar)
//
// We throw std::bad_alloc() when scalable_malloc returns NULL
//(we return NULL if it is a no-throw implementation)
void* operator new (size_t size) throw (std::bad_alloc)
{
if (size == 0) size = 1;
if (void* ptr = scalable_malloc(size))
return ptr;
throw std::bad_alloc();
}
void* operator new[](size_t size) throw (std::bad_alloc)
{
return operator new (size);
}
void* operator new (size_t size, const std::nothrow_t&) throw ()
{
if (size == 0) size = 1;
if (void* ptr = scalable_malloc(size))
return ptr;
return NULL;
}
void* operator new[](size_t size, const std::nothrow_t&) throw ()
{
return operator new (size, std::nothrow);
}
void operator delete (void* ptr) throw ()
{
if (ptr != 0) scalable_free(ptr);
}
void operator delete[](void* ptr) throw ()
{
operator delete (ptr);
}
void operator delete (void* ptr, const std::nothrow_t&) throw ()
{
if (ptr != 0) scalable_free(ptr);
}
void operator delete[](void* ptr, const std::nothrow_t&) throw ()
{
operator delete (ptr, std::nothrow);
}
int main(int argc, char** argv)
{
unsigned long long ARRAYSIZE = 20ULL * 1024ULL * 1024ULL * 1024ULL;
tbb::task_scheduler_init tbb_init;
unsigned __int16 *myBuff = new unsigned __int16[ARRAYSIZE];
if (0 != __cilkrts_set_param("nworkers", "10")){
std::cout << "Error" << std::endl;
}
const clock_t begintime = clock();
cilk_for(long long j = 0; j < ARRAYSIZE; ++j){
myBuff[j] = 0;
}
std::cout << "finish: " << float(clock() - begintime) / CLOCKS_PER_SEC << std::endl;
std::cin.get();
delete [] myBuff;
return 0;
}
(以上代码改编自 James Reinders,O'REILLY 的 Intel TBB 书籍)但结果几乎与之前的尝试相同。我设置了 TBB_VERSION 环境变量,看看我是否真的使用Scalable_malloc 和得到的信息在这张图中(nworkers = 32):
https://www.dropbox.com/s/y1vril3f19mkf66/TBB_Info.png?dl=0
我愿意知道我的代码有什么问题。我预计内存写入速度至少约为 40 GB/s。
我应该如何正确使用可伸缩分配器?
有人可以提供一个使用 INTEL TBB 的可扩展分配器的简单验证示例吗?
环境:英特尔至强 CPU E5-2690 0 @ 2.90 GHz(2 个处理器),224 GB 内存(2 * 7 * 16 GB)DDR3 1600 MHz,Windows 服务器 2008 R2 数据中心,Microsoft Visual Studio 2013 和 Intel C++ 编译器 2017。
最佳答案
来自 wikipedia : "DDR3-xxx 表示数据传输速率,描述 DDR 芯片,而 PC3-xxxx 表示理论带宽(截断最后两位数字),用于描述组装的 DIMM。带宽是通过每秒传输数乘以计算得出的八。这是因为 DDR3 内存模块在 64 数据位宽的总线上传输数据,并且由于一个字节包含 8 位,这相当于每次传输 8 个字节的数据。”
因此单个模块 DDR3-1600 最大能够达到 1600*8 = 12800 MB/s让您的系统有 4 个 channel (每个处理器),您应该能够达到:
12800 * 4 = 51200 MB/s - 51.2 GB/s,这就是 CPU specifications 中的说明方式
你总共有两个 CPU 和 8 个 channel :你应该能够达到它的两倍,并行工作。但是,您的系统是 NUMA 系统 - 在这种情况下内存放置很重要......
每个 channel 可以放置多个内存库。当在 channel 中放置更多模块时,您会减少可用时序 - 例如,PC-1600 可能表现为 PC-1333 或更少 - 这通常在主板规范中报告。示例 here .
您有七个 模块——您的 channel 不是平均分配的……您的带宽受到最慢 channel 的限制。建议 channel 彼此相等。
如果您降频到 1333,您可以期待:1333 * 8 = 10666 MB/s 每 channel :
每个 CPU 42 GB/s
channel 在寻址空间中交错分布,您在对内存块进行清零时会使用所有 channel 。只有在使用 strip 访问访问内存时,您才会遇到性能问题。
TBB 可扩展分配让许多线程优化内存分配。也就是说,分配时没有全局锁,内存分配不会被其他线程事件限制。这就是操作系统分配器中经常发生的事情。
在您的示例中,您根本没有使用很多分配,只有一个主线程。你正试图获得最大内存带宽。使用不同的分配器时,内存访问不会改变。
阅读评论我看到你想优化内存访问。
用对 memset() 的单个调用替换归零循环,并让编译器对其进行优化/内联。 -/O2 应该足够了。
英特尔编译器用优化的内部函数/内联调用替换了许多库调用(memset、memcpy 等)。在这种情况下——即,将一大块 ram 归零——内联并不重要,但使用优化的内在函数非常重要:它将使用流指令的优化版本:SSE4.2/AVX
然而,基本的 libc memset 将胜过任何手写循环。至少在 Linux 上。
关于c++ - 使用 INTEL TBB 的可扩展内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46523375/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!