Multithreading 如何并行执行自定义函数公式,同时保持谷歌工作表的共享性和无权限?

Multithreading 如何并行执行自定义函数公式,同时保持谷歌工作表的共享性和无权限?,multithreading,google-apps-script,google-sheets,mapreduce,custom-function,google-cloud-functions,Multithreading,Google Apps Script,Google Sheets,Mapreduce,Custom Function,Google Cloud Functions,我有一个谷歌表格,上面有一个自定义的函数公式:从电子表格中获取一个矩阵和两个向量,进行一些冗长的矩阵向量计算(>30秒,因此超出了配额),然后将结果输出为一组行。它是单线程的,因为Google Apps脚本(GAS)本来就是这样的,但是我想使用多线程解决方案来并行计算,所以它可以大大加快计算速度 要求(1-3): UX:它应该作为自定义函数公式自动、反应性地运行计算,这意味着用户不必通过单击运行按钮或类似按钮手动启动计算。就像我目前的单线程版本一样 Parallelizable:理想情况下,它应

我有一个谷歌表格,上面有一个自定义的函数公式:从电子表格中获取一个矩阵和两个向量,进行一些冗长的矩阵向量计算(>30秒,因此超出了配额),然后将结果输出为一组行。它是单线程的,因为Google Apps脚本(GAS)本来就是这样的,但是我想使用多线程解决方案来并行计算,所以它可以大大加快计算速度

要求(1-3):

  • UX:它应该作为自定义函数公式自动、反应性地运行计算,这意味着用户不必通过单击运行按钮或类似按钮手动启动计算。就像我目前的单线程版本一样

  • Parallelizable:理想情况下,它应该产生约30个线程/进程,这样就不必像现在那样花费>30秒(由于谷歌的原因,它会超时),而应该花费约1秒。(我知道气体是单螺纹的,但有一些变通方法,请参考下文)

  • 可共享性:理想情况下,我应该能够与其他人共享该工作表,以便他们可以“复制”该工作表,并且脚本仍将为他们运行计算:

    • 3.1无权限:无需我手动将个人权限分发给用户(无权限)。例如,每当有人“复制”和。我的初步测试表明这是可能的
    • 3.2非侵入性的:电子表格用户无需给予提示性授权,如“允许此电子表格/脚本/应用程序访问您的整个Google Drive或Gmail帐户?”。只要仍保持要求3.1,就可以接受必须对脚本/Web应用程序进行非侵入性授权的用户
    • 3.3UX:不强制用户查看电子表格中的HTML侧栏
  • 我已经阅读了@TheMaster的文章,其中概述了在Google Apps脚本中解决并行化的一些潜在方法。解决方案#3
    google.script.run
    和解决方案#4
    UrlFetchApp.fetchAll
    (都使用谷歌Web应用程序)看起来最有希望。但有些细节我不知道,比如他们是否能遵守要求1和3及其子要求

    我可以设想另一种可能的天真解决方法,将函数拆分为几个自定义函数公式,并在电子表格本身内部进行并行化(通过某种映射/约简)(将中间结果存储回电子表格,并让自定义函数公式作为约简器处理)。但对我来说,这是不受欢迎的,而且可能是不可行的

    我非常确信我的函数可以使用某种Map/Reduce过程进行并行化。函数当前通过在内存中执行所有计算进行优化,在步骤之间不接触电子表格,最后将结果输出到电子表格。它的细节相当复杂,超过100行,所以我不想用更多(并且可能会混淆)的信息让您负担过重,这些信息实际上不会影响本案例的普遍适用性。对于这个问题的上下文,你可以假设我的函数是可并行的(和MAP还原),或者考虑任何你已经知道的函数。有趣的是,Google Apps脚本中的并行化通常可以实现什么,同时还可以保持最高级别的共享性和用户体验。如果需要,我会用更多细节更新这个问题

    更新2020-06-19:

    更清楚地说,我并不完全排除Google Web App的变通方法,因为我没有经验了解它们的实际限制,无法确定它们是否能够在需求范围内解决问题。我已更新子要求3.1和3.2以反映这一点。我还添加了子需求3.3,以便更清楚地了解意图。我还删除了req4,因为它在很大程度上与req1重叠

    我还编辑了这个问题,并删除了相关的子问题,因此它更侧重于标题中的单个主要HOWTO问题。我问题中的要求应提供一个明确的客观标准,在这方面,答案将被视为最佳答案


    我意识到,正如@TheMaster私下指出的那样,这个问题可能是搜索Google Sheet多线程解决方案的圣杯。理想情况下,Google将提供一个或多个功能来支持多线程、map reduce或更多无权限共享。但在此之前,我真的很想知道,在目前的限制条件下,什么是最佳的解决办法。我希望这个问题也与其他人相关,即使考虑到严格的要求。

    如果您发布的web应用中包含“任何人,甚至匿名”,以“我”的身份执行,则自定义函数可以使用
    UrlFetchApp.fetchAll
    发布到该web应用。这将并行运行。这解决了所有三个要求

    这里需要注意的是:如果多人使用该表单,并且自定义函数必须发布到“同一”webapp(您发布该应用以执行您的操作)进行处理,谷歌将限制同时执行

    要解决此问题,您可以要求使用您的工作表的用户发布他们自己的web应用程序。开始时,他们必须执行一次,无需授权


    如果没有,您需要为负载托管一个自定义服务器或类似的东西,这可能会有所帮助。

    我最终使用了我在帖子中提到的天真的解决方法:

    我可以设想另一种可能的天真的解决办法,那就是 将函数拆分为多个自定义函数公式并执行以下操作 内部的并行化(通过某种Map/Reduce) 电子表格本身(将中间结果存储回 电子表格
        function didAnyExecutedIntervalFail(intervalsExecuted, ...intervalOutputs) {
          const errorValues = new Set(["#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A","#ERROR!", "#"]);
          // We go through only the outputs for intervals which were included in the parallel execution.
          for(let i=0; i < intervalsExecuted; i++) {
            if (errorValues.has(intervalOutputs[i]))
              return "Result below is not valid (due to errors in one or more of the intervals), even though it looks like a proper result!";
          }
        }