Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Clojure中执行并行事务_Clojure_Stm - Fatal编程技术网

如何在Clojure中执行并行事务

如何在Clojure中执行并行事务,clojure,stm,Clojure,Stm,我有一系列需要并行处理的客户。我试着用一个pmap。结果非常缓慢,比顺序实现慢得多。内部函数处理客户有一个事务。显然,pmap会一次启动所有事务,最后重试以降低性能。你最好的并行化方法是什么 (defn process-customers [customers] (doall (pmap (fn [sub-customers] (doseq [customer sub-customers] (process-customer cus

我有一系列需要并行处理的客户。我试着用一个
pmap
。结果非常缓慢,比顺序实现慢得多。内部函数
处理客户
有一个事务。显然,pmap会一次启动所有事务,最后重试以降低性能。你最好的并行化方法是什么

(defn process-customers [customers]
  (doall 
    (pmap 
      (fn [sub-customers]
        (doseq [customer sub-customers]
          (process-customer customer)))
      (partition-all 10 customers))))
编辑
处理客户
功能包括以下步骤。我写这些步骤是为了简洁。所有步骤都在一个事务中,以确保另一个并行事务不会导致负库存等不一致

(defn- process-customer [customer]
  "Process `customer`. Consists of three steps:
  1. Finding all stores in which the requested products are still available.
  2. Sorting the found stores to find the cheapest (for the sum of all products).
  3. Buying the products by updating the `stock`.
)
编辑2:下面版本的
流程客户
与上面的并行
流程客户
具有相同的性能。下面的内容显然是连续的

(defn process-customers [customers]
  "Process `customers` one by one. In this code, this happens sequentially."
  (doseq [customer customers]
    (process-customer customer)))

我假设您的交易在
流程客户的整个生命周期内锁定了库存。这将是缓慢的,因为所有的客户都在为同一个宇宙的商店竞争。如果您可以将流程分为两个阶段:1)报价和2)履行,并仅在(2)上应用事务,那么性能应该会更好。或者,如果您购买了
agent
programming,您将在消息级别自动定义事务边界。以下是您可以考虑的一个示例:

(defn获得最佳交易
“返回给定订单与给定门店(代理)的最佳交易”
[物料订购]
;;
;向1000家商店索取报价(并行)
;;
(doseq[商店]
(发送存储获取报价订单)
;;
;等待答复,最多0.5秒
;;
(申请等待500家店铺)
;;
分类并找到最好的商店
;;
(当让[最佳存储(->>存储
(过滤器(fn[store](进入@store[:quotes order]))
(排序方式(fn[store](>>(进入@store[:引号顺序])
瓦尔斯
(减少+))
第一)]
{:最佳商店最佳商店
:发票id(do)
执行命令
(发送最佳商店订单)
;等待交易完成
(等待最佳商店)
获取发票id
(进入@best store[:发票订单])})
要从1000家商店中找到100种产品的100份订单(共289项商品)的最优惠价格:

(->>订单
(pmap(部分优惠商店))
(过滤器:发票id)
计数
时间)
;; => 57
;; “运行时间:312.002328毫秒”
示例业务逻辑:

(defn获取报价)
“通过检查库存发出报价”
[存储{:键[订单项]:按订单}]
(如果让[报价(->>订购项目
(减少库存
{:商店
:quote nil})
:引述)]
;具有生成报价的库存
(店内关联[:报价订单]报价)
没有存货
(更新存储:quotes dissoc order)))
(定义)
“如果先前报价,则完成订单”
[店单]
(如果让[报价(入库[:报价订单])]
再次检查库存并生成发票
(让[[发票库存]](检查库存并生成发票存储订单)]
(条件->商店
发票(->
登记发票
(在[:发票订单]发票中关联)
使报价无效
(更新:quotes dissoc order)
更新库存
(助理:存货)
以前没有引用过
(商店)

在不知道处理需要什么、预期的性能特征是什么等的情况下,我不知道如何才能对此负责。请尝试提供一个——其他人可以运行的最短代码来模拟问题并测试他们提出的解决方案。(一个好的解决方案可能是,f/e,使事务的逻辑可交换;当然,除非我们能看到它,否则我们无法判断这是否可行)。@charlesduff,我有一个编辑。请注意,这是一个通过一系列商店进行查看并获得最便宜商店的交易。如果顾客想购买不止一种产品,他必须从最便宜的商店购买所有产品。这可能不可能表述为交换的。那家商店的存货随后减少了。当然,我们不想要负库存。顺便问一下——是什么具体的操作使得这个过程变慢,从而使并行化变得重要?是否有外部(数据库或其他I/O操作)查找?没有长时间运行的进程。这似乎就是你要问的问题:)。我只是在屏幕上登录。我还可以关闭日志记录。我在想,因为我正在处理许多客户,并行化将带来性能提升。必须保持一致的共享资源
stock
似乎是一个瓶颈。整个“商店”现在都是代理。我有两个问题。1.如果然后运行多个线程,它们的引用和实现请求是否不会一次执行一个?2.如果是这样的话,这和顺序实现不一样吗?从商店的角度来看,工作单元是在报价发出后完成的。然后它可以立即切换到服务其他客户/订单。客户可以花时间做出自己的购买决定,而不会阻塞任何商店。这只是反映了多线程/任务在实际场景中的工作方式。顺便说一句,代理编程只是建模解决方案的一种方法。如果在方法中应用了适当的锁定粒度,则可以获得类似的吞吐量。类似于行锁(一个存储)和表锁(存储的宇宙)