Articles of multithreading

如何在C ++中提前分配内存?

总体情况 对带宽,CPU使用率和GPU使用率都非常敏感的应用程序需要每秒从一个GPU向另一个GPU传输大约10-15GB的数据。 它使用DX11 API来访问GPU,因此上传到GPU只能在需要映射每个单独上传的缓冲区时发生。 上传一次以25MB的大小发生,16个线程同时向缓冲区写入缓冲区。 关于这一点,没有什么可以做的。 写入的实际并发级别应该较低,如果它不是以下错误。 这是一个带有3 Pascal GPU,高端Haswell处理器和四通道RAM的强大工作站。 在硬件上没有太多可以改进的地方。 它运行的是Windows 10的桌面版本。 实际问题 一旦我传递了大约50%的CPU负载, MmPageFault()某些东西(在Windows内核中,当访问已映射到您的地址空间但尚未被操作系统提交的内存时调用)破坏严重,其余50% MmPageFault()的旋转锁正在浪费CPU负载。 CPU使用率达到100%,应用程序性能完全降低。 我必须假设,这是由于每秒需要分配给进程的大量内存,而且每次DX11缓冲区未映射时,这些内存也完全没有映射到进程中。 相应地,实际上每秒有数千次对MmPageFault()的调用,随着memcpy()被顺序写入缓冲区而顺序发生。 每遇到一个未提交的页面。 一旦CPU负载超过50%,保护页面pipe理的Windows核心中的乐观旋转locking会完全降低性能。 注意事项 缓冲区由DX11驱动程序分配。 没有什么可以调整分配策略。 使用不同的内存API,特别是重复使用是不可能的。 调用DX11 API(映射/取消映射缓冲区)全部来自单个线程。 实际的复制操作可能发生在multithreading上,而不是系统中的虚拟处理器。 减less内存带宽的要求是不可能的。 这是一个实时应用程序。 事实上,硬性限制目前是主要GPU的PCIe 3.0 16x带宽。 如果可以的话,我已经需要进一步推进了。 避免使用multithreading副本是不可能的,因为有独立的生产者 – 消费者队列,这些队列不能被轻易地合并。 自旋锁性能的下降似乎是非常罕见的(因为使用案例推得这么远),在Google上,你不会发现自旋锁函数名称的单一结果。 升级到对映射(Vulkan)进行更多控制的API正在进行中,但它不适合作为短期修复。 由于相同的原因,切换到更好的操作系统内核目前不是一种select。 减lessCPU负载也不起作用; 除了(通常微不足道的和廉价的)缓冲拷贝外,还有太多的工作需要完成。 问题 可以做什么? 我需要显着减less个别页面错误的数量。 我知道映射到我的进程的缓冲区的地址和大小,我也知道内存还没有被提交。 我怎样才能确保尽可能less的交易提交内存? DX11的exception标志,它可以防止取消映射后的缓冲区解除分配,Windows API强制在单个事务中提交,几乎任何东西都是值得欢迎的。 目前的状态 // In the processing […]

_fread_nolock,_fseek_nolock的用途是什么?

我们有一个基本上从二进制文件中读取和写入向量的C ++类。 将单个向量载入内存的示例性读取函数如下所示: int load (const __int64 index, T* values) const { int re = _fseeki64(_file, index * _vectorSize + _offsetData, SEEK_SET); assert(re == 0); size_t read = fread(values, sizeof(T), _vectorElements, _file); assert(read == _vectorElements); return 0;} Out程序是OpenMP的multithreading,multithreading同时访问同一个文件。 为了避免由于multithreading引起的问题,我们总是覆盖OpenMP临界语句中的函数调用: #pragma omp critical { load(…); } 我知道Microsoft Visual C ++运行时包含_fseek_nolock , _fread_nolock , _fwrite_nolock等几个函数…例如_fread_nolock()函数被描述为 这个函数是fread的一个非locking版本。 除了不受其他线程的干扰之外,它与fread相同。 […]

Java ProcessBuilder:结果进程挂起

我一直在尝试使用Java的ProcessBuilder在Linux中启动应该“长期”运行的应用程序。 这个程序运行的方式是启动一个命令(在这种情况下,我启动一个媒体播放应用程序),让它运行,并检查,以确保它没有崩溃。 例如,检查PID是否仍然有效,然后重新启动进程,如果它已经死了。 我现在得到的问题是,PID在系统中保持活动状态,但应用程序的GUI挂起。 我尝试将ProcessBuilder(cmd).start()转换为一个单独的线程,但似乎没有解决任何问题,正如我所希望的那样。 基本上,对于用户来说,程序APPEARS已经崩溃,但是杀死驱动ProcessBuilder.start()进程的Java进程实际上允许创build的进程恢复其正常行为。 这意味着Java应用程序中的某些内容正在干扰生成的进程,但我完全不知道在这一点上是什么。 (因此,为什么我试图把它分成另一个线程,这似乎没有解决任何问题) 如果有人有任何意见或build议,请让我知道,因为我不能为了我的生活而想到如何解决这个问题。 编辑:我不关心从stream程创build的I / Ostream,因此没有采取任何措施来处理 – 这可能会导致stream程本身的挂起?

检查线程是否完成的正确方法?

我正在使用_beginthread在我的应用程序multithreading,现在等待,直到所有的线程完成我有全局布尔值设置为true每个线程完成,所以我在一个while循环,直到那时。 必须有一个更干净的方式来做到这一点? 谢谢

将parameter passing给_beginthreadex

我正在尝试使用_beginthreadex进行一些基本的并行化,并按照我给出的示例传递参数,但是它不起作用。 有任何想法吗? #include <iostream> #include <process.h> void MyThread(void *data) { std::cout << "Hello World!"; } int main() { _beginthreadex(NULL, 0, MyThread, NULL, 0, NULL); while(true); } 编辑: 为什么不传递NULL作为参数工作? (由于该函数无论如何不采取任何论点?) 作为参数列表传递NULL与_beginthread工作正常。

导致故障转储的Java错误的解决方法

我开发的程序偶尔会因为这个bug而崩溃: http : //bugs.java.com/bugdatabase/view_bug.do?bug_id=8029516 。 不幸的是,这个错误还没有被Oracle解决,并且错误报告说没有已知的解决方法。 我试图通过在KeyWatcher线程中调用.register(sWatchService,eventKinds)来修改bug报告中的示例代码,而将所有挂起的注册请求添加到我在KeyWatcher线程中循环的列表中,但仍然崩溃。 我猜这跟sWatchService上的同步效果一样(就像bug报告的提交者一样)。 你能想办法解决这个问题吗?

线程启动时的竞态条件?

我正在运行下面的代码来启动我的线程,但是它们不是按照预期启动的。 出于某种原因,一些线程以相同的对象开始(有些甚至不启动)。 如果我尝试debugging,他们开始就好(通过点击F10添加额外的延迟来逐步通过代码)。 这些是我的表单应用程序中的function: private void startWorkerThreads() { int numThreads = config.getAllItems().Count; int i = 0; foreach (ConfigurationItem tmpItem in config.getAllItems()) { i++; var t = new Thread(() => WorkerThread(tmpItem, i)); t.Start(); //return t; } } private void WorkerThread(ConfigurationItem cfgItem, int mul) { for (int i = 0; i < 100; i++) { Thread.Sleep(10*mul); } […]

跨平台等同于Windows事件

我试图移植一些Windows代码到Linux,理想情况下通过独立于平台的库(例如boost),但是我不知道如何移植这一点的事件代码。 代码位包含两个线程(让我们称之为A和B)。 A想要做的事情只有B可以,所以它发送一个消息,然后等待B说完成。 在Windows中,这看起来像这样: void foo();//thread a calls this void bar(HANDLE evt); void foo() { HANDLE evt = CreateEvent(0,FALSE,FALSE,0); bCall(boost::bind(&bar, evt)); WaitForSingleObject(evt,INFINITE); CloseHandle(evt); } void bar(HANDLE evt) { doSomething(); SetEvent(evt); } 我查看了boost :: thread库,但似乎没有任何这样做,closures我可以看到的是boost :: condition_variable,但它似乎意味着与一个互斥的结合,这是不是这里。

有效的线程数

我想优化我的应用程序线程数量。 几乎所有的CPU都有相同的IO值。 在系统中没有其他应用程序运行时,线程的有效数量是多less。 我想要Windows和JVM下的答案。

如何正确地终止一个dll内的挂起的线程?

大家好, 我有一个包含错误的第三方库。 当我调用一个函数时,它可能会挂起。 库函数在dll中调用。 我决定把呼叫转移到线程中,等待一段时间。 如果线程完成,然后确定。 如果不是 – 我应该终止它的强制性。 这里简单的例子: unsigned Counter = 0; void f() { HANDLE hThread; unsigned threadID; // Create the second thread. hThread = (HANDLE)_beginthreadex( NULL, 0, DoSomething, NULL, 0, &threadID ); if (WAIT_TIMEOUT == WaitForSingleObject( hThread, 5000 )) { TerminateThread(hThread, 1); wcout << L"Process is Timed Out"; } else { […]