当我在Windows 7中运行我的CUDA应用程序时(相对于Linux),我注意到了性能上的巨大打击.我想我可能知道减速发生的位置:无论出于何种原因,Windows Nvidia驱动程序(版本331.65)在通过运行时API调用时不会立即调度CUDA内核.为了说明这个问题,我描述了mergeSort应用程序(来自CUDA 5.5附带的示例).
首先考虑在Linux中运行时的内核启动时间:

接下来,考虑在Windows中运行时的启动时间:

这篇文章表明问题可能与批量启动内核的Windows驱动程序有关.无论如何我可以禁用这个批处理吗?
我使用的是GTX 690 GPU,Windows 7和Nvidia驱动程序的331.65版本.
假设我有一个整数序列:
0,1,2, ..
并希望根据给定的最后3个整数来预测下一个整数,例如:
[0,1,2]->5,[3,4,5]->6等
假设我像这样设置模型:
batch_size=1
time_steps=3
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, time_steps, 1), stateful=True))
model.add(Dense(1))
Run Code Online (Sandbox Code Playgroud)
据我了解,模型具有以下结构(请原图):
第一个问题:我的理解正确吗?
请注意,我已经画出了C_{t-1}, h_{t-1}进入图片的先前状态,因为指定时会暴露出来stateful=True。在这个简单的“下一个整数预测”问题中,应通过提供此额外的信息来改善性能(只要先前的状态是由前三个整数产生的)。
这使我想到了一个主要问题: 似乎标准做法(例如,参见此博客文章和TimeseriesGenerator keras预处理实用程序)是在训练过程中向模型提供一组交错的输入。
例如:
batch0: [[0, 1, 2]]
batch1: [[1, 2, 3]]
batch2: [[2, 3, 4]]
etc
Run Code Online (Sandbox Code Playgroud)
这让我感到困惑,因为这似乎需要第一Lstm单元的输出(对应于第一时间步长)。看这个图:

从tensorflow docs:
stateful:布尔值(默认为False)。如果为True,则批次中索引i的每个样本的最后状态将用作下一个批次中索引i的样本的初始状态。
似乎此“内部”状态不可用,并且所有可用状态都是最终状态。看这个图:

因此,如果我的理解是正确的(显然不是这样),那么在使用时是否不应该将不重叠的样本窗口馈送到模型中stateful=True?例如:
batch0: [[0, 1, 2]]
batch1: [[3, 4, 5]]
batch2: [[6, 7, 8]]
etc
Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,我在用户系统上的GPU之间分配处理负载.基本上,每个GPU都有CPU线程,当主应用程序线程定期触发时,它会启动GPU处理间隔.
考虑以下图像(使用NVIDIA的CUDA探查器工具生成)作为GPU处理间隔的示例- 此处应用程序使用单个GPU.

正如您所看到的,两个排序操作消耗了大部分GPU处理时间,而我正在使用Thrust库(thrust :: sort_by_key).此外,看起来push :: sort_by_key会在启动实际排序之前调用几个cudaMallocs.
现在考虑应用程序在两个GPU上分散处理负载的相同处理间隔:

在完美的世界中,您可以预期2 GPU处理间隔恰好是单GPU的一半(因为每个GPU的工作量只有一半).正如你所看到的,部分原因并非如此,因为cudaMallocs由于某种争用问题而被同时调用(有时长2-3倍)时似乎需要更长的时间.我不明白为什么会出现这种情况,因为2个GPU的内存分配空间是完全独立的,因此cudaMalloc上不应该有系统范围的锁定 - 每GPU锁定会更合理.
为了证明我的假设问题是同时使用cudaMalloc调用,我创建了一个非常简单的程序,它有两个CPU线程(每个GPU),每个线程多次调用cudaMalloc.我首先运行此程序,以便单独的线程不会同时调用cudaMalloc:

你看,每次分配需要大约175微秒.接下来,我用同时调用cudaMalloc的线程运行程序:

在这里,每个呼叫比前一个案例花了大约538微秒或3倍!毋庸置疑,这极大地减慢了我的应用程序,并且理所当然,只有2个以上的GPU才会使问题变得更糟.
我在Linux和Windows上注意到了这种行为.在Linux上,我使用的是Nvidia驱动程序版本319.60,而在Windows上我使用的是327.23版本.我正在使用CUDA工具包5.5.
可能的原因: 我在这些测试中使用的是GTX 690.这张卡基本上是2 680个GPU,安装在同一个单元中.这是我运行的唯一"多GPU"设置,所以cudaMalloc问题可能与690的2 GPU之间的硬件依赖性有关吗?
NVIDIA Nsight Visual Studio Edition似乎无法同时调试CPU(主机代码)和GPU(cuda代码).使用Nsight Eclipse Edition(或cuda-gdb)这非常简单,例如,您可以从主机执行"介入"到CUDA内核.如何使用Visual Studio做同样的事情?
我继承了一些旧代码,似乎在某处内存泄漏。我的本能是
-faddress=sanitize -fno-omit-frame-pointer
Run Code Online (Sandbox Code Playgroud)
然后让Address Sanitizer的工具系列为我找到泄漏点。但是,我感到非常失望。我希望收到某种运行时错误消息(类似于您不应读写的地址清理程序的错误)。直到程序成功完成之后,泄漏清理器才似乎不进行任何泄漏检查分析。我的问题是,我继承的代码具有多个线程,而并非旨在将所有线程都加入以准备软着陆。
我用一个简单的例子简化了我的问题:
#include <thread>
#include <chrono>
#include <iostream>
bool exit_thread = false;
void threadFunc()
{
while(!exit_thread)
{
char* leak = new char[256];
std::this_thread::sleep_for(std::chrono::seconds{1});
}
}
int main() {
std::thread t(threadFunc);
std::cout << "Waiting\n";
std::this_thread::sleep_for(std::chrono::seconds{5});
exit_thread = true;
std::cout << "Exiting\n";
//Without joining here I do not get the leak report.
t.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用这个编译
clang++ leaker.cpp -fsanitize=address -fno-omit-frame-pointer -g -O0 -std=c++1y -o leaker
Run Code Online (Sandbox Code Playgroud)
然后跑
ASAN_OPTIONS='detect_leaks=1' LSAN_OPTIONS='exitcode=55:report_objects=true:log_threads=true:log_pointers=true' ./leaker
Run Code Online (Sandbox Code Playgroud)
(我在这里对“ LSAN_OPTIONS”有点疯狂,因为我在玩耍……没有一个选项可以满足我的要求,但是一旦得知泄漏就退出了)。
如代码中所述,如果我加入线程然后退出程序,则会得到一个漂亮的泄漏报告。否则我什么也得不到。正如你可以成像追踪到遗留代码库10-100线程,并把他们都下去好听点是笨重。
几年前,我记得玩过Visual Leak …
我正在将一些C++代码移植到Windows(来自Linux/g ++ 4.8.1),我注意到Microsoft的持续时间模数运算符的实现是不正确的.
简单的程序
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main(void)
{
std::cout << (milliseconds(1050)%seconds(1)).count() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用Microsoft Visual Studio 2012编译时会出现编译错误:
error C2228: left of '.count' must have class/struct/union
Run Code Online (Sandbox Code Playgroud)
标准(http://en.cppreference.com/w/cpp/chrono/duration/operator_arith4)的定义为
template< class Rep1, class Period1, class Rep2, class Period2 >
typename common_type<duration<Rep1,Period1>, duration<Rep2,Period2>>::type
constexpr operator%( const duration<Rep1,Period1>& lhs,
const duration<Rep2,Period2>& rhs );
Run Code Online (Sandbox Code Playgroud)
即模数运算符返回公共类型的持续时间.Microsoft的实现(http://msdn.microsoft.com/en-us/library/hh874810.aspx)定义为
template<class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<Rep1, Rep2>::type
operator%(
const duration<Rep1, Period1>& Left,
const …Run Code Online (Sandbox Code Playgroud)