【论文阅读】Efficient Model-Stealing Attacks Against Inductive Graph Neural Networks(2024)

摘要

Graph Neural Networks(图神经网络) (GNNs) are recognized as(被认为) potent tools(有力工具) for processing(处理) real-world data organized in graph structures(以图结构组织的现实世界数据). Especially inductive GNNs(归纳GNNs), which enable the processing of graph-structured data(图结构数据) without(不需要) relying on(依赖) predefined graph structures(预定义的图结构), are gaining importance in an increasingly wide variety of applications(越来越广泛的应用). As these networks demonstrate proficiency(熟练) across a range of tasks(一系列任务), they become lucrative targets(成为有利可图的目标) for model-stealing attacks(模型窃取攻击) where an adversary seeks to(寻求) replicate the functionality of the targeted network(复制目标网络的功能).
Large efforts(巨大努力) have been made to develop model-stealin

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果要使用Work-Stealing Queue来实现函数一个函数顺序执行,可以将每个函数封装成一个任务,并将这些任务添加到共享的任务队列中。然后,每个线程维护自己的任务队列,并从中取出任务执行,如果自己的队列为空,就从其他线程的队列中“偷”任务执行。 下面是一个使用Work-Stealing Queue实现函数一个函数顺序执行的简单代码示例: ```c++ #include <iostream> #include <thread> #include <vector> #include <deque> #include <atomic> #include <random> std::deque<std::function<void()>> task_queue; std::vector<std::thread> threads; std::atomic<bool> stop_flag{false}; std::vector<std::deque<std::function<void()>>> thread_queues; void worker(int id) { std::default_random_engine engine(id); std::uniform_int_distribution<int> distribution(0, threads.size() - 1); while (!stop_flag) { std::function<void()> task; bool found = false; // 从自己的任务队列中取出任务执行 if (!thread_queues[id].empty()) { task = thread_queues[id].front(); thread_queues[id].pop_front(); found = true; } else { // 从其他线程的任务队列中“偷”任务执行 for (int i = 0; i < threads.size(); ++i) { int index = (id + i) % threads.size(); if (!thread_queues[index].empty()) { task = thread_queues[index].back(); thread_queues[index].pop_back(); found = true; break; } } } // 如果没有找到任务并且任务队列为空,则等待一段时间再继续查找任务 if (!found && task_queue.empty()) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); continue; } // 如果找到了任务,则执行任务 if (found) { task(); } else { // 否则,从任务队列中取出任务并执行 std::lock_guard<std::mutex> lock{task_queue_mutex}; if (!task_queue.empty()) { task = task_queue.front(); task_queue.pop_front(); task(); } } } } void func1() { std::cout << "Function 1" << std::endl; } void func2() { std::cout << "Function 2" << std::endl; } void func3() { std::cout << "Function 3" << std::endl; } int main() { // 创建多个线程 for (int i = 0; i < std::thread::hardware_concurrency(); ++i) { thread_queues.emplace_back(); threads.emplace_back(worker, i); } // 将函数封装成任务并添加到共享的任务队列中 task_queue.emplace_back([]() { func1(); }); task_queue.emplace_back([]() { func2(); }); task_queue.emplace_back([]() { func3(); }); // 等待任务执行完成 while (!task_queue.empty()) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } // 设置停止标志,等待线程结束 stop_flag = true; for (auto& thread : threads) { thread.join(); } return 0; } ``` 在上面的示例中,我们首先创建多个线程,并将每个线程维护自己的任务队列。然后,我们将函数封装成任务并添加到共享的任务队列中。每个线程循环执行以下操作: 1. 从自己的任务队列中取出任务执行。 2. 如果自己的队列为空,则从其他线程的队列中“偷”任务执行。 3. 如果任务队列为空,则等待一段时间再继续查找任务。 最后,我们等待任务执行完成,设置停止标志,等待线程结束。 这样,我们就可以使用Work-Stealing Queue实现函数一个函数顺序执行的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bosenya12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值