2012-01-31 70 views
4

编辑:根据PlasmaHH的建议增加了带有内存位置的调试输出。cl :: vector vs std :: vector:不同的迭代器行为

我不明白cl :: vector <>在OpenCL的C++绑定中的不同行为。考虑下面的代码:

部首Top.hpp

class Top { 
public: 
    void setBool(bool b); 
    bool getBool(); 
private: 
    bool status; 
}; 

Top.cpp

#include "Top.hpp" 

void Top::setBool(bool b) { 
    std::cout << (void*)this << " setBool("<< b<< ")\n"; 
    status = b; 
} 

bool Top::getBool() { 
    std::cout << (void*)this << " getBool() returns " << status << std::endl; 
    return status; 
} 

使用以上:

#define __NO_STD_VECTOR 

#include <iostream> 
#include "CL/cl.hpp" 
#include "Top.hpp" 

using namespace cl; 
using namespace std; 

cl::vector<Top> js; 

int main() { 
    js.push_back(Top()); 
    js[0].setBool(true); 
    cout << js[0].getBool() << endl; 
    for(cl::vector<Top>::iterator i = js.begin(); i != js.end(); ++i) { 
     (*i).setBool(false); 
    } 
    cout << js[0].getBool() << endl; 
} 

随着__NO_STD_VECTOR在std ::矢量被覆盖。输出是

0x6021c0 setBool(1) 
0x6021c0 getBool() returns 1 
0x7fffae671d60 setBool(0) 
0x6021c0 getBool() returns 1 

所以迭代器返回的位置肯定是错误的。

使用上述与std::vector(并更改命名空间,当然std),但是给人的预期输出:

0x1be0010 setBool(1) 
0x1be0010 getBool() returns 1 
0x1be0010 setBool(0) 
0x1be0010 getBool() returns 0 

这个迭代器作用不同,但它应该更换的std ::向量避免兼容性问题。我错过了什么吗?

+1

尝试添加类似'std :: cout <<(void *)this <<“setBool(”<< b <<“)\ n”;'到你的setBool函数(类似于getBool)来看看正在进行,以及在哪里设置,如果有的话。这样你可以看到它是否迭代,或者东西是“指向”错误的元素等。 – PlasmaHH 2012-01-31 15:20:19

+0

在任何情况下,'std :: vector'行为都是我所期望的。我无法想象为什么'cl :: vector'会做一些奇怪的事情...... – Xeo 2012-01-31 15:31:16

+0

@Xeo:是的,预计是'std :: vector'。 @PlasmaHH:的确,由迭代器返回的对象具有不同的内存地址,所以它不会返回我的对象​​并在其他地方设置“false”。 – rdoubleui 2012-01-31 15:34:56

回答

4

不是任何想象力的OpenCL专家,但我很感兴趣,所以我去了CUDA/OpenCL Computing。我似乎他们的*符返回一个副本,而不是参考:

00706   T operator *() 
00707   { 
00708    return vec_[index_]; 
00709   } 

鉴于(第一,非const)载体[]操作返回一个参考:

00621  T& operator[](int index) 
00622  { 
00623   return data_[index]; 
00624  } 
00625 
00626  T operator[](int index) const 
00627  { 
00628   return data_[index]; 
00629  } 

尝试通过矢量迭代直接(使用旧的“int i = 0,...”),看看是否给出了不同的结果。如果是这样,您可能需要输入一个错误报告(首先检查),因为这是*运算符的意外行为。

+0

我可以证实类似数组的方法(原谅缺乏适当的术语)有效(正如上面的例子'js [0] .setBool(false)')。 – rdoubleui 2012-01-31 17:13:36

+0

Erp!我应该注意到了!那么,我会说要联系AMD(或者你的图书馆的任何人)并询问是否有意。这当然不是我期望它行动的方式。 – 2012-01-31 19:17:14

+0

不幸的是它是一个Nvidia芯片,所以我打赌他们只是在等待我的错误报告......但我会看看。 – rdoubleui 2012-01-31 20:18:39

1

从地址判断我怀疑这是一个64位版本,并且cl向量的迭代器的operator*正在通过值返回而不是通过引用返回,而不允许访问原始元素。作为一个实验,你可以尝试使用->运营商,而不是i->setBool(false);,看看它是否健全。

+0

' - >'运算符不起作用,编译器抱怨:' - >'的基本操作数具有非指针类型'cl :: vector :: iterator'。我有点遗憾解释这一点。 – rdoubleui 2012-01-31 16:10:18

+1

@rdoubleui:这意味着迭代器似乎没有重载'operator->'。 – Xeo 2012-01-31 16:46:15