无法对可扩展方法进行多线程处理

2024-04-25

更新:为了帮助澄清我的要求,我发布了一些java代码来表达这个想法。

前段时间我问了一个question https://stackoverflow.com/questions/7265576/can-brute-force-algorithms-scale/7265593#7265593关于如何获得一种算法来分解一组数字,我们的想法是给它一个数字列表(1,2,3,4,5)和总计(10)并且它会计算出每个数字的所有倍数,加起来等于总数('1*10' or '1*1,1*2,1*3,1*4' or '2*5',ETC..)。这是我做过的第一个编程练习,所以我花了一段时间才让它工作,但现在我想尝试看看是否可以扩展它。最初问题中的人说它是可扩展的,但我对如何做到这一点有点困惑。递归部分是我坚持缩放组合所有结果的部分的区域(它引用的表不可扩展,但应用缓存我能够使其快速)

我有以下算法(伪代码):

//generates table
for i = 1 to k
    for z = 0 to sum:
        for c = 1 to z / x_i:
            if T[z - c * x_i][i - 1] is true:
                set T[z][i] to true

//uses table to bring all the parts together
function RecursivelyListAllThatWork(k, sum) // Using last k variables, make sum
    /* Base case: If we've assigned all the variables correctly, list this
     * solution.
     */
    if k == 0:
        print what we have so far
        return

    /* Recursive step: Try all coefficients, but only if they work. */
    for c = 0 to sum / x_k:
       if T[sum - c * x_k][k - 1] is true:
           mark the coefficient of x_k to be c
           call RecursivelyListAllThatWork(k - 1, sum - c * x_k)
           unmark the coefficient of x_k

我真的不知道如何线程/多重处理 RecursivelyListAllThatWork 函数。我知道如果我向它发送一个较小的 K(它是列表中项目总数的整数),它将处理该子集,但我不知道如何组合子集中的结果。例如,如果列表是[1,2,3,4,5,6,7,8,9,10]我发送 K=3 然后只处理 1,2,3 这很好,但是如果我需要包含 1 和 10 的结果怎么办?我试图修改表(变量 T),所以只有我想要的子集在那里,但仍然不起作用,因为,像上面的解决方案一样,它做了一个子集,但无法处理需要更广泛范围的答案。

如果有人可以解释如何从概念上打破这个递归步骤以便可以使用其他核心/机器,我不需要任何代码。

更新:我似乎仍然不知道如何将 RecursivelyListAllThatWork 变成可运行的(我在技术上知道如何做到这一点,但我不明白如何更改 RecursivelyListAllThatWork 算法以便它可以并行运行。其他部分只是为了让示例工作,我只需要在 RecursivelyListAllThatWork 方法上实现 runnable )。这是java代码:

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class main
{
    public static void main(String[] args)
    {
        System.out.println("starting..");
        int target_sum = 100;
        int[] data = new int[] { 10, 5, 50, 20, 25, 40 };
        List T = tableGeneator(target_sum, data);
        List<Integer> coeff = create_coeff(data.length);
        RecursivelyListAllThatWork(data.length, target_sum, T, coeff, data);
    }

    private static List<Integer> create_coeff(int i) {
        // TODO Auto-generated method stub
        Integer[] integers = new Integer[i];
        Arrays.fill(integers, 0);
        List<Integer> integerList = Arrays.asList(integers);
        return integerList;
    }


    private static void RecursivelyListAllThatWork(int k, int sum, List T, List<Integer> coeff, int[] data) {
        // TODO Auto-generated method stub
        if (k == 0) {
            //# print what we have so far
            for (int i = 0; i < coeff.size(); i++) {
                System.out.println(data[i] + " = " + coeff.get(i));
            }

            System.out.println("*******************");
            return;
        }

        Integer x_k = data[k-1];
        //  Recursive step: Try all coefficients, but only if they work. 
        for (int c = 0; c <= sum/x_k; c++) { //the c variable caps the percent
            if (T.contains(new Point((sum - c * x_k), (k-1))))
            {
                    // mark the coefficient of x_k to be c
                    coeff.set((k-1), c);
                    RecursivelyListAllThatWork((k - 1), (sum - c * x_k), T, coeff, data);
                    // unmark the coefficient of x_k
                    coeff.set((k-1), 0);
            }

        }

    }

    public static List tableGeneator(int target_sum, int[] data) {
        List T = new ArrayList();
        T.add(new Point(0, 0));

        float max_percent = 1;
        int R = (int) (target_sum * max_percent * data.length);
        for (int i = 0; i < data.length; i++)
        {
            for (int s = -R; s < R + 1; s++)
            {
                int max_value = (int) Math.abs((target_sum * max_percent)
                        / data[i]);
                for (int c = 0; c < max_value + 1; c++)
                {
                    if (T.contains(new Point(s - c * data[i], i)))
                    {
                        Point p = new Point(s, i + 1);
                        if (!T.contains(p))
                        {
                            T.add(p);
                        }
                    }
                }
            }
        }
        return T;
    }
} 

多线程的一般答案是通过堆栈(后进先出或先入先出)来取消递归实现。当实现这样的算法时,线程的数量是算法的固定参数(例如核心的数量)。

为了实现它,当测试条件结束递归时,语言调用堆栈被替换为存储最后上下文作为检查点的堆栈。在你的情况下是k=0 or coeff值与目标总和匹配。

去递归之后,第一个实现是运行多个线程来消耗堆栈,但堆栈访问成为争用点,因为它可能需要同步。

更好的可扩展解决方案是为每个线程专用一个堆栈,但需要在堆栈中初始生成上下文。

我提出了一种混合方法,其中第一个线程递归地工作有限数量的线程k作为最大递归深度:示例中的小数据集为 2,但如果较大,我建议使用 3。然后,第一部分将生成的中间上下文委托给一个线程池,该线程池将处理剩余的内容k具有非递归实现。该代码不是基于您使用的复杂算法,而是基于相当“基本”的实现:

import java.util.Arrays;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MixedParallel
{
    // pre-requisite: sorted values !!
    private static final int[] data = new int[] { 5, 10, 20, 25, 40, 50 };

    // Context to store intermediate computation or a solution
    static class Context {
        int k;
        int sum;
        int[] coeff;
        Context(int k, int sum, int[] coeff) {
            this.k = k;
            this.sum = sum;
            this.coeff = coeff;
        }
    }

    // Thread pool for parallel execution
    private static ExecutorService executor;
    // Queue to collect solutions
    private static Queue<Context> solutions;

    static {
        final int numberOfThreads = 2;
        executor =
            new ThreadPoolExecutor(numberOfThreads, numberOfThreads, 1000, TimeUnit.SECONDS,
                                   new LinkedBlockingDeque<Runnable>());
        // concurrent because of multi-threaded insertions
        solutions = new ConcurrentLinkedQueue<Context>();
    }


    public static void main(String[] args)
    {
        int target_sum = 100;
        // result vector, init to 0
        int[] coeff = new int[data.length];
        Arrays.fill(coeff, 0);
        mixedPartialSum(data.length - 1, target_sum, coeff);

        executor.shutdown();
        // System.out.println("Over. Dumping results");
        while(!solutions.isEmpty()) {
            Context s = solutions.poll();
            printResult(s.coeff);
        }
    }

    private static void printResult(int[] coeff) {
        StringBuffer sb = new StringBuffer();
        for (int i = coeff.length - 1; i >= 0; i--) {
            if (coeff[i] > 0) {
                sb.append(data[i]).append(" * ").append(coeff[i]).append("   ");
            }
        }
        System.out.println(sb.append("from ").append(Thread.currentThread()));
    }

    private static void mixedPartialSum(int k, int sum, int[] coeff) {
        int x_k = data[k];
        for (int c = sum / x_k; c >= 0; c--) {
            coeff[k] = c;
            int[] newcoeff = Arrays.copyOf(coeff, coeff.length);
            if (c * x_k == sum) {
                //printResult(newcoeff);
                solutions.add(new Context(0, 0, newcoeff));
                continue;
            } else if (k > 0) {
                if (data.length - k < 2) {
                    mixedPartialSum(k - 1, sum - c * x_k, newcoeff);
                    // for loop on "c" goes on with previous coeff content
                } else {
                    // no longer recursive. delegate to thread pool
                    executor.submit(new ComputePartialSum(new Context(k - 1, sum - c * x_k, newcoeff)));
                }
            }
        }
    }

    static class ComputePartialSum implements Callable<Void> {
        // queue with contexts to process
        private Queue<Context> contexts;

        ComputePartialSum(Context request) {
            contexts = new ArrayDeque<Context>();
            contexts.add(request);
        }

        public Void call() {
            while(!contexts.isEmpty()) {
                Context current = contexts.poll();
                int x_k = data[current.k];
                for (int c = current.sum / x_k; c >= 0; c--) {
                    current.coeff[current.k] = c;
                    int[] newcoeff = Arrays.copyOf(current.coeff, current.coeff.length);
                    if (c * x_k == current.sum) {
                        //printResult(newcoeff);
                        solutions.add(new Context(0, 0, newcoeff));
                        continue;
                    } else if (current.k > 0) {
                        contexts.add(new Context(current.k - 1, current.sum - c * x_k, newcoeff));
                    }
                }
            }
            return null;
        }
    }
}

您可以检查哪个线程找到了输出结果,并检查所有涉及的线程:递归模式下的主线程和上下文堆栈模式下池中的两个线程。

现在这个实现是可扩展的data.length高:

  • 最大递归深度限制在低级别的主线程
  • 池中的每个线程都使用自己的上下文堆栈,不会与其他线程争用
  • 现在要调整的参数是numberOfThreads and maxRecursionDepth

所以答案是肯定的,你的算法可以并行化。这是基于您的代码的完全递归实现:

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class OriginalParallel
{
    static final int numberOfThreads = 2;
    static final int maxRecursionDepth = 3;

    public static void main(String[] args)
    {
        int target_sum = 100;
        int[] data = new int[] { 50, 40, 25, 20, 10, 5 };
        List T = tableGeneator(target_sum, data);
        int[] coeff = new int[data.length];
        Arrays.fill(coeff, 0);
        RecursivelyListAllThatWork(data.length, target_sum, T, coeff, data);
        executor.shutdown();
    }

    private static void printResult(int[] coeff, int[] data) {
        StringBuffer sb = new StringBuffer();
        for (int i = coeff.length - 1; i >= 0; i--) {
            if (coeff[i] > 0) {
                sb.append(data[i]).append(" * ").append(coeff[i]).append("   ");
            }
        }
        System.out.println(sb.append("from ").append(Thread.currentThread()));
    }

    // Thread pool for parallel execution
    private static ExecutorService executor;
    static {
        executor =
            new ThreadPoolExecutor(numberOfThreads, numberOfThreads, 1000, TimeUnit.SECONDS,
                                   new LinkedBlockingDeque<Runnable>());
    }

    private static void RecursivelyListAllThatWork(int k, int sum, List T, int[] coeff, int[] data) {
        if (k == 0) {
            printResult(coeff, data);
            return;
        }
        Integer x_k = data[k-1];
        //  Recursive step: Try all coefficients, but only if they work. 
        for (int c = 0; c <= sum/x_k; c++) { //the c variable caps the percent
            if (T.contains(new Point((sum - c * x_k), (k-1)))) {
                    // mark the coefficient of x_k to be c
                    coeff[k-1] = c;
                    if (data.length - k != maxRecursionDepth) {
                        RecursivelyListAllThatWork((k - 1), (sum - c * x_k), T, coeff, data);
                    } else {
                        // delegate to thread pool when reaching depth 3
                        int[] newcoeff = Arrays.copyOf(coeff, coeff.length);
                        executor.submit(new RecursiveThread(k - 1, sum - c * x_k, T, newcoeff, data)); 
                    }
                    // unmark the coefficient of x_k
                    coeff[k-1] = 0;
            }
        }
    }

    static class RecursiveThread implements Callable<Void> {
        int k;
        int sum;
        int[] coeff;
        int[] data;
        List T;

        RecursiveThread(int k, int sum, List T, int[] coeff, int[] data) {
            this.k = k;
            this.sum = sum;
            this.T = T;
            this.coeff = coeff;
            this.data = data;
            System.out.println("New job for k=" + k);
        }

        public Void call() {
            RecursivelyListAllThatWork(k, sum, T, coeff, data);
            return null;
        }
    }

    public static List tableGeneator(int target_sum, int[] data) {
        List T = new ArrayList();
        T.add(new Point(0, 0));

        float max_percent = 1;
        int R = (int) (target_sum * max_percent * data.length);
        for (int i = 0; i < data.length; i++) {
            for (int s = -R; s < R + 1; s++) {
                int max_value = (int) Math.abs((target_sum * max_percent) / data[i]);
                for (int c = 0; c < max_value + 1; c++) {
                    if (T.contains(new Point(s - c * data[i], i))) {
                        Point p = new Point(s, i + 1);
                        if (!T.contains(p)) {
                            T.add(p);
                        }
                    }
                }
            }
        }
        return T;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法对可扩展方法进行多线程处理 的相关文章

  • V8 如何管理它的堆?

    我知道V8的垃圾收集在工作时 会从GC的root开始追踪 这样无法到达的对象就会被标记然后被清除 我的问题是GC是如何遍历那些对象的 必须有一个数据结构来存储所有可达或不可达的对象 位图 链接表 顺便说一句 JVM 也做同样的事情吗 艾伦秀
  • JPanel透明背景和显示元素[重复]

    这个问题在这里已经有答案了 我插入一个背景图e 变成 aJPanel但一些界面元素消失了 以下 Java Swing 元素不会出现 标签标题 标签 usuario 标签 密码 按钮加速器 你能否使图像透明或元素不透明 setOpaque f
  • 使用 jdbc 程序连接到 Open Office odb 文件

    我编写了以下代码来连接到 OpenOffice db String db C Documents and Settings hkonakanchi Desktop Test odb Class forName org hsqldb jdbc
  • JUnit 使用 Mockito 测试异步方法

    我已经使用 Spring Framework 版本 5 0 5 RELEASE 在 Java 1 8 类中实现了异步方法 public class ClassToBeTested Autowired private MyComponent
  • JUnit Eclipse 显示 System.out.print() 的

    我正在使用 JUnit 3 和 Eclipse 3 4 当我运行 JUnit 测试用例时 一切正常并且测试完美完成 唯一的事情是我想查看我正在运行的类的输出 所有类都具有一些输出值的基本 System out print 因此 当我运行测试
  • 从 eclipse 运行时 java.io.FileNotFoundException: (没有这样的文件或目录)

    我正在写入文件并想要控制台输出 TODO Create a game engine and call the runGame method public static void main String args throws Excepti
  • 删除 servlet 中的 cookie 时出现问题

    我尝试使用以下代码删除 servlet 中的 cookie Cookie minIdCookie null for Cookie c req getCookies if c getName equals iPlanetDirectoryPr
  • 如何在 OpenAPI 3.0 中定义字节数组

    我正在将 API 从 Swagger 2 0 迁移到 OpenAPI 3 0 在 DTO 中 我有一个指定为字节数组的字段 Swagger 对 DTO 的定义 Job type object properties body type str
  • 如何消除警告:使用“$”而不是“.”对于 Eclipse 中的内部类

    我是 Android 开发新手 当我将 eclipse 和 Android SDK 更新到最新版本后 我收到警告 Use instead of for inner classes or use only lowercase letters
  • Java 的 QP 求解器 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 会话 bean 中的 EntityManager 异常处理

    我有一个托管无状态会话 bean 其中注入了 EntityManager em 我想做的是拥有一个具有唯一列的数据库表 然后我运行一些尝试插入实体的算法 但是 如果实体存在 它将更新它或跳过它 我想要这样的东西 try em persist
  • java JFileChooser 文件大小过滤器

    我知道我可以按文件类型进行过滤 但是可以按文件大小进行过滤吗 例如 JFileChooser 仅显示 3 MB 以内的图片 简短的回答应该是 你尝试过什么 长答案是肯定的 JFileChooser fc new JFileChooser f
  • 如何使用 Java 原生接口从 Java 调用 Go 函数?

    可以通过以下方式调用 C 方法JNA https en wikipedia org wiki Java Native AccessJava 中的接口 如何使用 Go 实现相同的功能 package main import fmt impor
  • .class 与 .java

    class 文件和 java 文件有什么区别 我正在尝试让我的小程序工作 但目前我只能在 Eclipse 中运行它 还不能嵌入 HTML 谢谢 编辑 那么如何使用 JVM 进行编译呢 class 文件是编译后的 java 文件 java 都
  • 字节码和位码有什么区别[重复]

    这个问题在这里已经有答案了 可能的重复 LLVM 和 java 字节码有什么区别 https stackoverflow com questions 454720 what are the differences between llvm
  • 使用 Maven 3 时 Cobertura 代码覆盖率为 0%

    读完这篇文章后 将 Cobertura 与 Maven 3 0 2 一起使用的正确方法是什么 https stackoverflow com questions 6931360 what is the proper way to use c
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • Android 中的字符串加密

    我正在使用代码进行加密和加密 它没有给出字符串结果 字节数组未转换为字符串 我几乎尝试了所有方法将字节数组转换为字符 但没有给出结果 public class EncryptionTest extends Activity EditText
  • 如何在Java中跨类共享变量,我尝试了静态不起作用

    类 Testclass1 有一个变量 有一些执行会改变变量的值 现在在同一个包中有类 Testclass2 我将如何访问 Testclass2 中变量的更新值 由 Testclass1 更新 试过这个没用 注意 Testclass1和Tes
  • 将隐藏(生物识别)数据附加到 pdf 上的数字签名

    我想知道是否可以使用 iText 我用于签名 或 Java 中的其他工具在 pdf 上添加生物识别数据 我会更好地解释一下 在手写板上签名时 我会收集签名信息 例如笔压 签名速度等 我想将这些信息 java中的变量 与pdf上的签名一起存储

随机推荐

  • C# 中的类型与强类型

    在 C 中 有什么理由说强类型与只是typed 当有人说类型化类时 我想到的是对象以外的某种类型 除了 object 之外 几乎所有内容都是用 C 编写的 一旦定义了一个不是对象的类 该类就是一种类型 不再从那里输入它 顺便说一句 这不是关
  • 为什么两个字符串文字相加不使用operator+?

    编辑 我已经重新格式化了帖子以使其更加清晰 为什么这有效 struct A struct B B A void operator const B const B int main A a1 a2 a1 a2 而这不 struct B B c
  • 排序数组中的最小成本路径

    给定一个排序数组A e g 4 9 10 11 19 搬家费用i gt j is abs A j A i 从给定元素开始 例如10 找出成本最低的路径 而无需两次访问同一元素 所以在这个例子中解决方案是10 gt 9 gt 4 gt 11
  • 将图像裁剪或遮罩成圆形

    使用 ImageMagick 或 GD 库将图像裁剪或遮罩成圆形形状的最佳方法是什么 请注意 解决方案存在于 其他 问答网站上 但不存在于 StackOverflow 上 这是使用 ImageMagick 的一种方法 无需使用遮罩即可实现此
  • Python 中的归一化互相关

    最近几天我一直在努力计算两对向量 x和y 的自由度 参考Chelton 1983 它是 根据 Chelton 1983 的自由度 https i stack imgur com O0DqE png 我找不到使用 np correlate 计
  • 像随机关卡生成一样自由流动,只有一种可能的解决方案?

    我已经实现了在这个问题中标记为正确答案的算法 流畅类游戏随机关卡制作用什么 https stackoverflow com questions 12926111 what to use for flow free like game ran
  • 在 Uvicorn/FastAPI 内发出下游 Https 请求的正确方法是什么?

    我有一个 API 端点 FastAPI Uvicorn 除此之外 它还向另一个 API 请求信息 当我使用多个并发请求加载 API 时 我开始收到以下错误 h11 util LocalProtocolError can t handle e
  • 如何在创建后将 VB.NET DataTable 列定义为主键

    我正在使用 VB NET dataAdapter 从 Oracle 数据库导入表 我使用 fill 命令将导入的数据添加到数据集中 在 DataTable 已填充数据后 如何将 DataTable 的特定列定义为 PrimaryKey 只要
  • 灵活地将新数据附加到 yaml 文件

    我有不同的 yaml 文件 它们可能具有不同的嵌套结构 文件1 yaml test3 service1 name1 somedata name2 somedata 文件2 yaml test1 app1 app2 somedata app7
  • 在远程服务器上执行 rake 任务

    生产环境的物理架构包括多台执行不同作业 rake 任务 的机器 所有这些机器都在同一个数据库上 其中一项工作将完成大量工作UPDATE如果其他作业正在运行 则通常会返回 postgres 死锁的表 我已经有一个 rake 任务来正常停止其他
  • 如何对字符串进行拼写检查?

    有人知道 C 多语言拼写检查库吗 我不需要实时拼写检查 仅检查字符串 thanks 就其价值而言 这是谷歌上的第一个点击 SpellCheck http msdn microsoft com en us library system win
  • 如何在本地闭包中调用非逃逸闭包? [复制]

    这个问题在这里已经有答案了 我有一个看起来像这样的函数 func test closure gt let localClosure closure localClosure 这只是一个例子 并不能完全反映我遇到的问题 显然在这里我可以直接打
  • 类型错误:“str”对象无法使用 input() 调用[重复]

    这个问题在这里已经有答案了 我有以下代码 它应该询问用户 2 文件名 我在第二个函数中的 input 中遇到错误 但在第一个函数中没有 我不明白 这是错误 输出 getOutputFile 文件 splitRAW py 第 22 行 位于
  • Keras:嵌入 LSTM

    在 LSTM 的 keras 示例中 用于对 IMDB 序列数据进行建模 https github com fchollet keras blob master examples imdb lstm py https github com
  • Azure 静态 Web 应用程序和 Azure Blob 存储静态网站有什么区别?

    有什么区别Azure Blob 存储静态网站 https learn microsoft com en us azure storage blobs storage blob static website host and Azure 静态
  • Spring boot 启动慢

    这是一个奇怪的问题 我们正在使用带有集成 tomcat 的 Spring Boot Web 应用程序 在我的本地 Mac 上 应用程序启动很快 几秒钟 在装有 Centos 7 的 google 机器上 启动速度非常慢 大约 2 分钟 应用
  • Swiftlint 覆盖与 SPM 相关的项目设置

    我遇到了 swiftlint 自动更正的奇怪行为 我的项目使用通过 SPM 导入的库 但是当我运行 linter 时 它会更改如下设置 B4621A7323D0A90F00545ADE LibraryName in Frameworks i
  • 解决合并冲突后 Git rebase 陷入困境

    我正在运行一个遇到冲突的变基 git rebase master First rewinding head to replay your work on top of it Applying Better SelectMotifsView
  • 在 Android 中解密从 .net 生成的 RSA 加密值

    我在这里浏览了很多帖子 但没有找到正确的解决方案 我想从 Android 解密在 c net 中加密的值 我已使用以下代码片段在 net平台中成功解密 public static void Main string privateKey Ba
  • 无法对可扩展方法进行多线程处理

    更新 为了帮助澄清我的要求 我发布了一些java代码来表达这个想法 前段时间我问了一个question https stackoverflow com questions 7265576 can brute force algorithms