tldr; 如何實作運行定時函式的 for 回圈std::index_sequence?
好的,我承認標題有點神秘,但我正在研究這個問題:在運行時甚至編??譯時是否可能有一個 for 回圈?
而且我可能對我可能做的事情太興奮了std::index_sequence。我會解釋我的目標是什么。我想要類似下面的代碼:
for(int i = 1; i < 100000; i)
{
auto start = time();
runOpenCL<i>();
std::cout << time() - start << std::endl;
}
編譯成這個(每個定時器都有):
runOpenCL<1>();
runOpenCL<2>();
runOpenCL<3>();
...
runOpenCL<100000>();
現在我認為這應該可以正常作業嗎?因為 for 回圈通常在編譯時以這種方式解釋(如果這是正確的短語)。但是,我知道模板對這種可能的狡猾代碼有一定的保護措施,所以我看到 std::index_sequence 可以解決這個問題,但我對模板代碼的理解不夠,無法弄清楚發生了什么。現在,在有人說我可以將其設為普通函式引數之前,是的,如果您查看函式本身,我可以這樣做:
template<int threadcount>
INLINE void runOpenCL()
{
constexpr int itemsPerThread = (MATRIX_HEIGHT threadcount - 1) / threadcount;
// executing the kernel
clObjs.physicsKernel.setArg(2, threadcount);
clObjs.physicsKernel.setArg(3, itemsPerThread);
clObjs.queue.enqueueNDRangeKernel(clObjs.physicsKernel, cl::NullRange, cl::NDRange(threadcount), cl::NullRange);
clObjs.queue.finish();
// making sure OpenGL is finished with its vertex buffer
glFinish();
// acquiring the OpenGL object (vertex buffer) for OpenCL use
const std::vector<cl::Memory> glObjs = { clObjs.glBuffer };
clObjs.queue.enqueueAcquireGLObjects(&glObjs);
// copying the OpenCL buffer to the BufferGL
clObjs.queue.enqueueCopyBuffer(clObjs.outBuffer, clObjs.glBuffer, 0, 0, planets_size_points);
// releasing the OpenGL object
clObjs.queue.enqueueReleaseGLObjects(&glObjs);
}
但我不想。我需要更好的理由嗎?我認為實作這一點真的很酷。只要它最終仍然可讀。
uj5u.com熱心網友回復:
這是一個可能的版本,它將使用 C 17 折疊運算式展開回圈:
#include <type_traits>
#include <utility>
template <std::size_t I>
void runOpenCL();
template <std::size_t... Is>
void runAllImpl(std::index_sequence<Is... >) {
// thanks @Franck for the better fold expression
(runOpenCL<Is>(), ...);
}
void runAll() {
runAllImpl(std::make_index_sequence<10000>{});
}
如果沒有 C 17,你可以做這樣的事情,但在非優化的構建中,你會得到一個巨大的堆疊爆炸:
#include <type_traits>
#include <utility>
template <std::size_t I>
void runOpenCL();
template <std::size_t... Is>
void runAllImpl(std::index_sequence<Is... >) {
int arr[]{ (runOpenCL<Is>(), 0)... };
(void)arr;
}
void runAll() {
runAllImpl(std::make_index_sequence<10000>{});
}
這似乎比@康桓偉的命題具有更大的價值,但(至少)GCC 無法編譯為 1000000(10000 是“好的”)。
uj5u.com熱心網友回復:
您可以在編譯時生成一個固定大小的函式表,并通過運行時索引呼叫表中的相應函式。例如像這樣:
#include <array>
template<std::size_t N>
constexpr auto gen_func_table = []<std::size_t... Is>
(std::index_sequence<Is...>) {
return std::array{ [] { runOpenCL<Is>(); }...};
}(std::make_index_sequence<N>{});
int main() {
constexpr std::size_t max_count = 100;
constexpr auto& func_table = gen_func_table<max_count>;
for(int i = 1; i < max_count; i)
func_table[i]();
}
演示。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/338993.html
