对于我的应用程序,我必须处理一堆对象(比如ints),这些对象随后被分割并分类成更小的桶.为此,我将元素存储在一个连续的数组中
arr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14...}
Run Code Online (Sandbox Code Playgroud)
并且关于桶(子列表)的信息由相应桶中的第一个元素的偏移量和子列表的长度给出.
所以,例如,给定
offsets = {0,3,8,..}
sublist_lengths = {3,5,2,...}
Run Code Online (Sandbox Code Playgroud)
会导致以下分裂:
0 1 2 || 3 4 5 6 7 || 8 9 || ...
Run Code Online (Sandbox Code Playgroud)
我正在寻找的只是使用自定义内核或thrust库在桶上运行算法(如减少)的一种通用且有效的方法.总结水桶应该给:
3 || 25 || 17 || ...
Run Code Online (Sandbox Code Playgroud)
我想出了什么:
选项1:自定义内核需要相当多的修补,复制到共享内存,正确选择块和网格大小以及自己的算法实现,如扫描,减少等.此外,每个操作都需要自己定制核心.总的来说,我很清楚如何做到这一点,但在thrust过去几天使用后,我的印象是可能有更聪明的方式
选项2:从偏移量({0,0,0,1,1,1,1,1,2,2,3,...}在上面的例子中)生成一个键数组并使用thrust::reduce_by_key.不过,我不喜欢额外的列表生成.
选项3:thrust::transform_iterator与...一起使用thrust::counting_iterator以生成上面给出的密钥列表.不幸的是,我无法想出一个实现,它不需要将索引增加到设备上的偏移列表,并且会破坏并行性.
实现这一目标最理智的方式是什么?
我很遗憾这个,我希望这里有人可以提供帮助.
我的应用程序包含数百个评估数字代码的函数(源代码各自在5MB范围内),我用std::map函数指针管理函数.显然发生的是当我尝试将参数传递给其中一个函数时,我得到一个堆栈溢出,由一个指向它的指针访问:
gdb输出:
Program received signal SIGSEGV, Segmentation fault.
0x0000000001ec0df7 in xsectiond149 (sme=Cannot access memory at address 0x7fffff34b888
) at xsection149.c:2
2 Poly3 xsectiond149(std::tr1::unordered_map<int, Poly3> & sme,
EvaluationNode::Ptr ti[], ProcessVars & s)
Run Code Online (Sandbox Code Playgroud)
和xsection149.c:2只有用于定义函数的左大括号.
/proc/<pid>/map 对于该过程显示最接近触发错误的地址的地址范围只有这一行:
7ffffff74000-7ffffffff000 rw-p 7ffffff73000 00:00 0 [stack]
Run Code Online (Sandbox Code Playgroud)
所以上面错误中的地址超出范围.
现在我的问题是:我如何解决这个问题?我无法解决我在堆上分配的问题...
在我的主要例程中发生的唯一想法是:
// A map containing O(10^4) Poly3 (struct with 6 doubles)
tr1::unordered_map<int, Poly3> smetemp;
// populates smetemp
computeSMEs(smetemp);
// Map of function pointers of type, O(10^3) elements
tr1::unordered_map<int, xsdptr> diagfunctions = get_diagram_map();
Run Code Online (Sandbox Code Playgroud)
怎么会溢出堆栈?
编辑:我试图在valgrind运行它,这是我得到的错误和谷歌没有提供任何有意义的信息:
valgrind: …Run Code Online (Sandbox Code Playgroud) 我有一个模板化的包装函数,它调用__global__像这样的 .cu 文件中定义的内核 ( )
template<typename T, class M>
__global__ void compute_kernel(T* input, T* output, n) {
M m;
// compute stuff using m
};
template<typename T, class M>
void compute(T* input, T* output, int n) {
// ... compute blocks, threads, etc.
compute_kernel<T,M> <<<dim_grid, dim_block>>>(input, output, n);
// ...
};
Run Code Online (Sandbox Code Playgroud)
和一个包含在主机代码中的头文件,它只有声明
template<typename T, class M>
void compute(T* input, T* output, int n);
Run Code Online (Sandbox Code Playgroud)
但是,compute()从带有任意模板参数的主机调用,编译失败,undefined reference to 'void reduce(...)'并且仅当我在.cu文件末尾添加专门化声明时,代码才会编译:
template void
compute<int, Method1<int> …Run Code Online (Sandbox Code Playgroud) 我的应用程序中有一个非常简单的功能,它可以完成大量工作并占用最多的计算时间:
f :: Int -> Array (Int,Int) Int -> [Int]
f x arr = [v | v <- range (l,u), vv <- [g!(x,v)], vv /= 0]
where ((_,l), (_,u)) = bounds arr
Run Code Online (Sandbox Code Playgroud)
这样做是:x从数组中的索引处提取一行arr并返回包含元素的所有列索引\= 0.因此,例如,给定以下带边界的矩阵((0,0),(2,2)):
arr = [[0, 0, 5],
[4, 0, 3],
[0, 3, 1]] -- for simplicity in [[a]] notation
Run Code Online (Sandbox Code Playgroud)
预期的产出是
f 0 arr == [2]
f 1 arr == [0,2]
f 2 arr == [1,2]
Run Code Online (Sandbox Code Playgroud)
我如何加速f和分析f(列表构造,数组访问等)实际占用大部分计算时间的更多细节?
谢谢!
在我的项目中,我已经实现了一个自定义内存分配器,以避免cudaMalloc在应用程序"预热"后不必要的调用.此外,我使用自定义内核进行基本数组填充,数组之间的算术运算等,并希望通过使用Thrust和删除这些内核来简化我的代码.设备上的每个数组都是通过原始指针创建和访问的(现在),我想在这些对象上使用 device_vector和Thrust方法,但我发现自己在原始指针和device_ptr<>所有时间之间进行转换,这有点使我的代码混乱.
我的相当模糊的问题:如何Thrust以最可读的方式组织自定义内存管理,数组方法和调用自定义内核的用法?
我试图在C++领域找到自己的方式,现在越来越困惑.玩具应用程序是一个非常基本的OpenGL引擎.所以这是(我想简单)问题:我想处理不同顶点数据的网格,所以我有例如
struct Vertex
{
Vector3f position;
}
struct VertexN : public Vertex
{
Vector3f normal;
}
Run Code Online (Sandbox Code Playgroud)
现在我需要一个Mesh类,它保存数据并绘制它.我尝试过这样的事情:
template<class T>
class Mesh
{
public:
Mesh();
~Mesh();
void load(const T * vertices, int num);
void draw();
protected:
T * vertices_;
Run Code Online (Sandbox Code Playgroud)
};
必须以不同方式加载和绘制不同的顶点,这可以通过模板特化来完成.
我的问题是我喜欢有另一个包含Mesh对象实例的类,但显然不允许使用模板化的类成员.
我能想到的另一个解决方案是在Mesh中保存指向基础结构Vertex的指针,为所使用的Vertex类型传递一个标识符,然后在load()和draw()中使用switch语句以允许不同的实现.
完成此任务的最佳方法是什么?
任何帮助是极大的赞赏.
我有一个算法的两个实现工作在数组上并返回一个单独的值,一个缓慢而天真但正确的方法A和一个优化的方法B,可能在输入参数空间的角落有问题.方法B根据输入数组的大小有分支,我想B针对A不同的输入数组大小进行测试.这两种方法都可以模仿不同的类型.
我刚开始第一次使用googletest,但我真的没有看到如何用夹具做一个明确的方法(以下是简化的,有更多的设置来进行测试,我我还想对数据进行其他测试:
template<typename T, unsigned int length> // type to test on, test array size
class BTest : public ::testing:Test {
public:
T* data; // test data
public:
BTest(); // allocate data, populate data with random elements
~BTest();
T run_method_a_on_data(); // reference: method A implementation
};
// ...
TYPED_TEST_CASE(...) // set up types, see text below
TYPED_TEST(...) {
// test that runs method B on data and compares to run_method_a_on_data() …Run Code Online (Sandbox Code Playgroud) 我遇到堆栈溢出问题,并希望确切地看到堆栈上的内容是什么.
如何使用GDB检查堆栈帧?是一个相同的问题,但info locals在这里看起来很好(很少变量,大多数是std :: vectors和std :: maps),所以我不希望堆栈从此溢出.此外,我已将堆栈限制设置为32MB,因此这应该是充足的,并且不使用递归函数.
是否有一个工具可以显示堆栈的完整内容,可能按大小排序?
对于模糊的问题很抱歉,但我希望有经验的Haskeller,这是一个明智的选择.
我必须表示和操作对称矩阵,因此数据类型基本上有三种不同的选择:
尽管如此,完整的矩阵存储(i,j)和(j,i)元素m(i,j) = m(j,i)
Data.Array(Int,Int)Int
一个地图,只存储(i,j)带有i <= j(上三角矩阵)的元素
Data.Map(Int,Int)Int
由索引索引的向量k,存储给定一些向量顺序的上三角矩阵f(i,j) = k
Data.Array Int Int
在矩阵上需要进行许多操作,更新单个元素,查询行和列等.但是,它们主要用作容器,不需要线性代数运算(反转,det等).
如果矩阵的维数将在附近,那么哪一个选项通常是最快的20x20?当我理解正确时,每次更新((//)在数组的情况下)都需要完整的副本,因此在案例2或3中从20x20=400元素到20*21/2 = 210元素会很有意义,但对于案例2和3的访问速度较慢.在某些时候需要转换.
有没有指导方针?
顺便说一句:第三种选择并不是一个非常好的选择,因为计算f^-1需要平方根.
我用来MathLink从C++应用程序发送和接收独立的mma表达式作为字符串.
std::string expression[N];
// ...
for(int i = 0; i < N; ++i) {
MLPutFunction(l, "EnterTextPacket", 1);
MLPutString(l, expression[i].c_str());
MLEndPacket(l);
// Check Packet ...
const char* result;
MLGetString(l, &result);
// process result ...
MLDisownString(l, result);
}
Run Code Online (Sandbox Code Playgroud)
我希望MLDisownString释放已用过的内存,除非它没有.
有任何想法吗?
我正在自动生成C代码来计算大型表达式,并试图用简单的例子弄清楚在单独的变量中预定义某些子部分是否有意义.
举个简单的例子,假设我们计算了一些形式:
#include <cmath>
double test(double x, double y) {
const double c[9][9] = { ... }; // constants properly initialized, irrelevant
double expr = c[0][0]*x*y
+ c[1][0]*pow(x,2)*y + ... + c[8][0]*pow(x,9)*y
+ c[1][1]*pow(x,2)*pow(y,2) + ... + c[8][1]*pow(x,9)*pow(y,2)
+ ...
Run Code Online (Sandbox Code Playgroud)
所有c [i] [j]正确初始化.实际上,这些表达式包含数以千万计的乘法和加法.
现在提出一个同事 - 减少对pow()的调用次数并缓存表达式中经常需要的值 - 在单独的变量中定义x和y的每个幂,这没什么大不了的,因为代码是自动的无论如何生成,像这样:
double xp2 = pow(x,2);
double xp3 = pow(x,3);
double xp4 = pow(x,4);
// ...
// same for pow(y,n)
Run Code Online (Sandbox Code Playgroud)
但是,我认为这是不必要的,因为编译器应该处理这些优化.
不幸的是,我没有阅读和解释汇编的经验,但我想我看到所有对pow()的调用都被优化了,这是对的吗?此外,编译器是否缓存pow(x,2),pow(x,3)等的值?
提前感谢您的意见!
给定一定的键顺序,如何对该列表排序多图(具有重复键的元组列表),其中重复元素的顺序无关紧要?
我正在寻找具有以下签名的功能
sortByList :: [(a,b)] -> [a] -> [(a,b)]
Run Code Online (Sandbox Code Playgroud)
例如,
a = [(1,'a'), (2, 'b'), (102, 'c'), (2, 'z')]
b = [2,102,1]
sortByList a b -- [(2,'b'), (2,'z'), (102, 'c'), (1, 'a')]
-- or [(2,'z'), (2,'b'), (102, 'c'), (1, 'a')]
-- (order in duplicate keys irrelevant)
Run Code Online (Sandbox Code Playgroud)
我有一些想法如何实现这一点,但它们看起来都很丑陋和繁琐(lookup在给定的多图上使用和重复查找和删除).
假设我的应用程序中需要一个新类型,它由一个std::vector<int>扩展的单个函数组成.直接的方式是组合(由于STL容器的继承限制):
class A {
public:
A(std::vector<int> & vec) : vec_(vec) {}
int hash();
private:
std::vector<int> vec_
}
Run Code Online (Sandbox Code Playgroud)
这要求用户首先在构造函数中构造一个vector<int>和一个副本,这在我们要处理大量的大向量时是不好的.当然,人们可以写一个传递push_back(),但这引入了可变状态,我想避免.
所以在我看来,我们可以避免复制或保持不可变,这是正确的吗?
如果是这样,最简单(和效率等效)的方法是在命名空间范围内使用typedef和free函数:
namespace N {
typedef std::vector<int> A;
int a_hash(const A & a);
}
Run Code Online (Sandbox Code Playgroud)
这只是在某种程度上感觉不对,因为未来的扩展将"污染"命名空间.此外,调用a_hash(...)any vector<int>是可能的,这可能会导致意外的结果(假设我们对用户必须遵循的A施加约束或者在第一个示例中强制执行)
我的两个问题是:
谢谢!
c++ ×9
cuda ×3
haskell ×3
arrays ×2
c ×2
thrust ×2
composition ×1
googletest ×1
list ×1
map ×1
mathlink ×1
multimap ×1
numeric ×1
optimization ×1
sorting ×1
stack ×1
unit-testing ×1